Click here to access the Canvas page with the repository for this assignment.
In this assignment you’ll use the combined power of Java and Arduino’s communications. Java will send user input data to the Arduino, and the Arduino will process those bytes and display their contents in Morse code. Morse code is an example of a substitution cipher (like the hex to binary substitution in the studio) because individual letters are replaced by a specific, fixed Morse code. Finally, the Arduino will send the Morse code back to Java to be displayed in the console.
By the end of this assignment you should have a better understanding of how data streams work and how they can be used. In addition, you will practice: iterating through arrays, working with ASCII characters, and transmitting data from and receiving data in both Arduino and Java.
We will be using the Java SerialComm
class, which you created during the
last studio. If you don’t yet have a functionally complete SerialComm
class (that supports debug
of both outgoing and incoming bytes), you will
want to finish that first.
The primary functions for interacting with Arduino’s incoming Serial
data
are Serial.available()
and
Serial.read()
. The Serial
object operations are also built on top of
Stream
objects.
Serial.available()
returns the number of bytes currently available to the
Serial.read()
function. Serial.read()
reads the next byte from the
stream.
You will also use morseEncode(char symbol)
, which has already been written
for you. morseEncode()
will return a String
that contains data
corresponding to the Morse code for a given symbol. Since Morse code
doesn’t have codes for lowercase letters, you will author a toUpper()
function that will convert lowercase characters to uppercase. This will
enable the morseEncode()
function (which already calls toUpper()
, meaning
you don’t have to edit morseEncode()
) to translate the alphanumeric
characters inputted to morse code. toUpper()
should have the following
parameters:
// Argument: Any character
// Return Value: Either:
// 1) If the character is a letter,
// the upper case equivalent.
// 2) If the character is not a letter,
// the original value.
char toUpper(char c) {
...
}
The easiest way to complete toUpper()
is to use the properties of ASCII values. If you look closely at the ASCII Table you’ll notice that a lower case letter can be converted to an upper case letter by changing just one bit, so you may want to review bitwise operations. Since the letters are numeric and in lexicographic order they can also be compared via the normal relational operators, like:
char c;
...
// Does this character come "at or after"
// the character for 0? (The character 1 would
/ come after 0, etc.)
if(c>='0') {
Using these properties of ASCII (being able to do comparisons, lexicographic ordering, and being able to manipulate bits) you can complete toUpper()
with just a few lines of code.
There are three files in the MorseCoder/
directory:
MorseCoder.ino
: This contains a nearly empty sketch. You will complete all your Arduino work here.MorseCodes.h
: This is called a header file (hence the “.h” extension) and contains things that need to read at the top (or head) of a source file to define features used later in the file. The MorseCoder.ino
Arduino file “includes” it to have access to the function defined in MorseCodes.cpp
. A header file and corresponding #include
are used somewhat like the import
statement in Java. Read through the comments which describe the function(s) you may need to use for this assignment.MorseCodes.cpp
: This contains a Morse code table and code that uses it. You do not need to modify it. Although you don’t need to understand the exact details of how morseEncode()
works to be able to use it, take a few minutes and read through it. You should notice that it uses the properties of ASCII in a few ways.Header files are an important part of code organization in C. They’re usually paired with a source file (Often with a “.c”, “.cc”, or “.cpp” extension). This separation helps for several reasons: it speeds up compile time, keeps code organized, and it can prevent errors due to order of declarations. Most importantly, the header is usually used to specify a public interface to functions whereas the corresponding source file provides private declarations. Often when you just need to use a function and don’t care about how it works you can simply refer to the header file.
Often a library of related functionality is contained in one source file (.cpp file) that may be used in many different projects. The MorseCodes files are a library that can be used to encode and decode Morse code.
Start by making the sketch in MorseCoder.ino
read in characters from the Serial Monitor and echo them back, as in the studio.
toUpper()
function and test it. Use it to ensure all the echoed characters are in upper case. For example, if the following is entered:
Don't shout at me!
It would be echoed back as:
DON'T SHOUT AT ME!
Use the morseEncode()
function to echo back the Morse code of the characters instead of the characters themselves. morseEncode()
will use your toUpper()
function, so there’s no need for you to call toUpper()
yourself. Read the comments in MorseCodes.h
for details of how you need to call morseEncode()
. You will
have to process each character of the Morse code separately. For example,
the morseEncode()
function will return a
String.
Serial.print()
rather than Serial.println()
. Please include one space ' '
between each letter of a word. So, “HI” would be sent as:
.... .. H I
Additionally, use three consecutive spaces ' '
to indicate the end of a word. “HI MOM” would then be:
.... .. -- --- -- H I M O M
'\n'
to indicate the end of a transmitted message. It acts as a way for both Java and the Arduino to know that the current message is over. It acts as a very simple example of a communication protocol which we will discuss in more detail in the coming weeks. For now, just know that it is important that both programs know when a transmission is over, so whenever your Arduino program receives a newline character '\n'
, make sure to transmit it back to Java. This can be accomplished by calling Serial.println()
with nothing in it or Serial.print("\n")
.Your final task is to author a Java program that performs very close to the same function as the Serial Monitor.
SerialComm.java
into the communication
directory, replacing the stub that is currently there. It should have the following abilities:
'\n'
after it has finished sending all characters from the user message to indicate that it has finished transmitting the message.'\n'
character.'\n'
character indicating that it is done receiving the encoded message, it should prompt the user for another message to encode.debug
in SerialComm
should be set to true
so that you can see the bytes as they go into and out of the Java program (to/from the Arduino).Verify that you have completed the following files:
- `MorseCoder/`
- `MorseCoder.ino`
- `MorseCodes.cpp`
- `MorseCodes.h`
- `communication/`
- `SerialComm.java`
Commit all your code. Do not ask to be checked out by a TA until after you have made certain that your work is committed. Failing to do this may result in you losing points on your assignment.
Follow the checklist below to see if you have everything done before demo your assignment to a TA.
toUpper()
works as it shouldSerial.read()
should only be invoked when data is available()
moreseEncode()
'.'
'-'
and ' '
to your Java program over the Serial portdebug
to display the outgoing and incoming dataCheck out with a TA.
Note: the formal rubric is on Canvas, this is just the highlights.
toUpper()
meets requirementsmorseEncode()
SerialComm
class has an appropriate readByte()
methodSerialComm
class has an appropriate writeByte()
methodSerialComm
class has an appropriate available()
method
Generated at 2022-07-20 19:49:20 +0000.
Page written by Julia Vogl, Bill Siever, Jeremy Goldstein, & Evan Simkowitz.