Go Down

Topic: custom void functions, how to use them? (Read 187 times) previous topic - next topic

IW7EHC

Jan 14, 2020, 05:54 am Last Edit: Jan 14, 2020, 05:58 am by IW7EHC
Hello experts,
I need some clarifications on how to use the custom made void functions.

This is a simple CW beacon, for the non "ham radio speaking" folks it's a circuit that is keying a transmitter on/off to send a string in Morse code.

So, this is my approach:
First I define the basic characters, the dot and the dash (di and dah) and all the different variables that are required to have the correct spacing between characters of the same letter, characters of the same word, two consecutive words.

My idea is to create a void function for dot and a void function for dash, and then combine them to define each letter,number,special character...

Then I would simply place the functions in loop,character after character,to compose the words I want to transmit.

For testing purpose, I've just defined 3 void functions:
dot
dash
letter V

Once I prove the concept is working, I'll add all the remaining letters and numbers.

I've been doing some reading on void functions, and found out that they were placed in different locations, sometimes after the end of loop, sometimes after the end of setup.
I'm getting confused now, I would like to understand where is the right place to put them.

Once more thing:
The void function defining the letter V (the same will apply to any other letter/number) is calling the other 2 void functions di(dot) and da(dash), is it going to work like this?
In other words:
since each character will be using a combination of the 2 main void functions dot and dash, is it ok to create a void function that has embedded void functions (recalls other void functions)?

Any chances the attached code will work?

Thanks

Code: [Select]



int Buz = A3;//
int Led = 6; //
int PotSpeed = A0;//
int PotFreq = A1;//

int Freq = 850;//

int Dit = 0 ;//
int Dah = 0 ; //
int InterLetter = 0 ;//
int BetweenLetters = 0 ; //
int BetweenWords = 0 ; //


void setup()

{

  pinMode(Led, OUTPUT);
  Serial.begin(1200);

}

void di() //
{
  tone(Buz, Freq); //
  digitalWrite(Led, HIGH);//
  delay(Dit);//
  noTone(Buz);//
  digitalWrite(Led, LOW); //

  delay(InterLetter);
}

void da() //
{
  tone(Buz, Freq); //
  digitalWrite(Led, HIGH);//
  delay(Dah);//
  noTone(Buz);//
  digitalWrite(Led, LOW); //

  delay(InterLetter);
}

void V()// di di di da (...-)
{
  di();
  delay(InterLetter);
  di();
  delay(InterLetter);
  di();
  delay(InterLetter);
  da();
  delay(BetweenLetters);
}

void loop()

{

  int Freq = map(analogRead(PotFreq), 0, 1023, 30, 4999); //
  int Dit = map(analogRead(PotSpeed), 0, 1023, 50, 150); //
  int Dah = 3 * Dit ; //
  int InterLetter = Dit ;//
  int BetweenLetters = 3 * Dit ; //
  int BetweenWords = 4 * Dit ; //

  {
    void V();
    void V();
    void V();
  }

  Serial.print("Freq=");  //
  Serial.print(Freq);  //
  Serial.print("  ");  //
  Serial.println(); //
  Serial.print("Dit=");  //
  Serial.print(Dit);  //
  Serial.print("  ");  //
  Serial.print("  Dah(3dit)=");  //
  Serial.print(Dah);  //
  Serial.print("  ");  //
  Serial.println(); //

  Serial.print("InterLetter(dit)=");  //
  Serial.print(InterLetter);  //
  Serial.print("  ");  //
  Serial.print("   BetweenLetters(3dit)=");  //
  Serial.print(BetweenLetters);  //
  Serial.print("  ");  //
  Serial.print("   BetweenWords(4dit)=");  //
  Serial.print(BetweenWords);  //
  Serial.print("  ");  //
  Serial.println(); //
  Serial.println(); //

}



UKHeliBob

What you are suggesting should work.  You can call a function from within another function with no problems but be sure not to construct an infinite loop where functionA() calls functionB() and vice versa, of course.

Your code is already cumbersome and will get worse as you add more letters to it.  Start by calling delay() for the gaps between di() and da() in those functions rather than in the letter function/  It will not matter to the compiler but the names of the delay periods could be confusing

Search the forum for Morse to see how other people have done it in much neater ways but good for for trying
Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

IW7EHC

Bob,
I'm aware that my approach is extremely low level on this, but I'm using it more as an opportunity to learn how to use functions, rather than anything else.

So, they're ok right were they are now?

I mean:

void setup()
{
…….
…….
}

All my functions HERE

void loop()
{
…..
…..
}

You've lost me here
Quote
Start by calling delay() for the gaps between di() and da() in those functions rather than in the letter function/

UKHeliBob

A C/C++ program requires that a function prototype be placed in the code before the actual function.  They are often placed at the start of the program for convenience.  In order to make the Arduino environment more friendly these prototypes are built for you and added to the code at the appropriate place as part of the compilation process so you don't need to put them in yourself.  There are actually exceptions to this, but you will not come across them for a while, if ever

The result is that you can put function definitions anywhere in an Arduino program apart from inside a another function.  Personally I put functions after setup() and loop() but do whatever suits you and makes the code easy to read, understand and maintain.

Quote
You've lost me here
Every time you call di() or da() in your program you call delay() afterwards
Code: [Select]

  di();
  delay(InterLetter);
  di();
  delay(InterLetter);

Why not call the delay() inside the di() and da() functions ?
Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

johnwasser

One problem with your sketch.  Inside loop() you have:
Code: [Select]
  int Freq = map(analogRead(PotFreq), 0, 1023, 30, 4999); //
  int Dit = map(analogRead(PotSpeed), 0, 1023, 50, 150); //
  int Dah = 3 * Dit ; //
  int InterLetter = Dit ;//
  int BetweenLetters = 3 * Dit ; //
  int BetweenWords = 4 * Dit ; //

This is defining LOCAL variables and assigning them values.  These are NOT assigning values to the GLOBAL variables that you functions are using.  To assign values to the GLOBAL variables that your functions use, don't declare new LOCAL variables:
Code: [Select]
  Freq = map(analogRead(PotFreq), 0, 1023, 30, 4999); //
  Dit = map(analogRead(PotSpeed), 0, 1023, 50, 150); //
  Dah = 3 * Dit ; //
  InterLetter = Dit ;//
  BetweenLetters = 3 * Dit ; //
  BetweenWords = 4 * Dit ; //


With those changes I think your sketch will work, allowing you to set the pitch and speed of the three 'V' letters.

Style pointers:
Don't put empty comments "//" at the ends of your lines.  They are of no use and clutter the code.
Change your pin number names from 'int' to 'const byte'.  It's a good habit because it allows the compiler to tell you if you are accidentally trying to change a pin number that should not change.
Add "Pin" to the pin number names.  This makes the use clearer.
There is no need to explicitly set GLOBAL variables to 0, especially where that value makes no sense.  The GLOBAL variables will default to 0.


Code: [Select]
const byte BuzPin = A3;
const byte LedPin = 6; 
const byte PotSpeedPin = A0;
const byte PotFreqPin = A1;


int Freq = 850;


int Dit;
int Dah; 
int InterLetter;
int BetweenLetters; 
int BetweenWords; 


void setup()
{
  pinMode(LedPin, OUTPUT);
  Serial.begin(1200);
}


void di() 
{
  tone(BuzPin, Freq); 
  digitalWrite(LedPin, HIGH);
  delay(Dit);
  noTone(BuzPin);
  digitalWrite(LedPin, LOW); 


  delay(InterLetter);
}


void da() 
{
  tone(BuzPin, Freq); 
  digitalWrite(LedPin, HIGH);
  delay(Dah);
  noTone(BuzPin);
  digitalWrite(LedPin, LOW); 


  delay(InterLetter);
}


void V() // di di di da (...-)
{
  di();
  delay(InterLetter);
  di();
  delay(InterLetter);
  di();
  delay(InterLetter);
  da();
  delay(BetweenLetters);
}


void loop()
{
  Freq = map(analogRead(PotFreqPin), 0, 1023, 30, 4999); 
  Dit = map(analogRead(PotSpeedPin), 0, 1023, 50, 150); 
  Dah = 3 * Dit ; 
  InterLetter = Dit ;
  BetweenLetters = 3 * Dit ; 
  BetweenWords = 4 * Dit ; 


  {
    void V();
    void V();
    void V();
  }


  Serial.print("Freq=");  
  Serial.print(Freq);  
  Serial.print("  ");  
  Serial.println(); 
  Serial.print("Dit=");  
  Serial.print(Dit);  
  Serial.print("  ");  
  Serial.print("  Dah(3dit)=");  
  Serial.print(Dah);  
  Serial.print("  ");  
  Serial.println(); 


  Serial.print("InterLetter(dit)=");  
  Serial.print(InterLetter);  
  Serial.print("  ");  
  Serial.print("   BetweenLetters(3dit)=");  
  Serial.print(BetweenLetters);  
  Serial.print("  ");  
  Serial.print("   BetweenWords(4dit)=");  
  Serial.print(BetweenWords);  
  Serial.print("  ");  
  Serial.println(); 
  Serial.println(); 
}
Send Bitcoin tips to: 1G2qoGwMRXx8az71DVP1E81jShxtbSh5Hp

IW7EHC

All of you, thanks for the useful tips.

John,
I gave your code a try, I couldn't get neither the LED or the Buzzer working.
I see on the serial monitor that the mapping from the frequency and speed pots is ok, but no audio/no blinking.

johnwasser

Oops... You had another mistake that I did not catch:

Code: [Select]
  {
    void V();
    void V();
    void V();
  }

That is NOT how you call a function.  That just says "If I use the name 'V' it is a function that takes no arguments and returns no value."... three times.  To actually CALL the function you just pass it arguments:

Code: [Select]
  {
    V();
   V();
   V();
  }


The brackets are harmless but completely unnecessary.

Style hint: 1200 baud was 'fast' in the early 1970's using an acoustic modem.  With direct hardware connections you should use a more modern baud rate, like 115200.  (Even the common '9600' is about 30 years out of date.)
Send Bitcoin tips to: 1G2qoGwMRXx8az71DVP1E81jShxtbSh5Hp

IW7EHC

All clear now.
John and Bob, thanks again for the help.

PS:
John,
I love your style hints, wish there were more  :)


Go Up