I'm working on a project with 2 arduinos- an Uno connected to a fingerprint scanner and SD reader, which communicates with a Mega controlling a touchscreen LCD. I feel as if I'm running into danger regarding memory, however, as I've already used 75% of the Uno's dynamic memory and I still have a decent amount of programming left to do.
const byte numChars = 25;
char receivedChars[numChars];
char uno;
char in;
boolean regng = false;
boolean voting = false;
boolean scanning = false;
boolean newData = false;
void setup() {
Serial.begin(9600);
Serial1.begin(9600);
}
void vote() {
Serial.print("vote");
}
void loop() {
if (Serial1.available() > 0) {
uno = Serial1.read();
if (uno == 'a') prompt();
else if (uno == 'b') reg();
else if (uno == 'c') vote();
}
}
void prompt() {
Serial.println("Enter 1 to register, or 2 to vote.");
if (Serial.available() > 0) {
in = Serial.read();
Serial1.write(in);
}
}
void recv() {
static byte ndx = 0;
char endMarker = '\n';
char rc;
while (Serial.available() > 0 || newData == false) {
if (Serial.available() > 0) {
rc = Serial.read();
if (rc != endMarker) {
receivedChars[ndx] = rc;
ndx++;
if (ndx >= numChars) {
ndx = numChars - 1;
}
}
else {
receivedChars[ndx] = '\0';
ndx = 0;
newData = true;
}
}
}
Serial1.write(receivedChars);
}
void reg() {
regng = true;
Serial1.write("r");
while (regng == true) {
if (Serial1.available() > 0) uno = Serial1.read();
if (uno == "F") {
Serial.print("First Name: ");
recv();
}
if (uno == "L") {
Serial.print("Last Name: ");
recv();
}
if (uno == "A") {
Serial.print("Age: ");
recv();
}
if (uno == "I") {
scanning = true;
while (scanning == true && Serial1.available() > 0) {
uno = Serial1.read();
if (uno == '0') Serial.println("Place finger on the scanner.");
if (uno == '1') Serial.println("Remove finger.");
if (uno == '2') Serial.println("Place finger on the scanner again.");
if (uno == '3') {
Serial.println("Scan complete!");
Serial.println("Registration successful.");
scanning = false;
regng = false;
}
if (uno == '4') {
Serial.println("Scan unsuccessful.");
scanning = false;
}
}
}
}
}
There are two primary functions of this program- to register a citizen, and then to allow someone to to cast a vote after verifying their identity. So far, only the registering function is complete, which is why I'm slightly concerned about my memory. The mega sketch is using the serial monitor as opposed to the touchscreen as I haven't implemented it yet. The question is, how could I modify or tweak the Uno's sketch to potentially save some space?
The libraries take up a certain amount of space. But only one copy of each function is used. Once you have used print() or println() once then using it 100 times more takes minimal to zero space.
This would be nice but I actually don't print anything to the hardware serial with the Uno.
That might be for other reasons. E.g. as pointed out by PaulS, you have an 3 element array and writing to element with index 3 writing can result in undefined behaviour.
what would be the difference between myFile.write() and myFile.print()?
print() converts the input to a string, and outputs the string one character at a time, using write().
write() outputs, be default, one byte/character.
The difference is irrelevant to the comment I made, though. Just because you tried to open the file does NOT mean that that was successful. If there is no File object created, you should NOT be trying to dereference that object. You must check that there is an object before you try to use it.
void sdWrite() // Functions start in column 1.
{ // Open braces go on their own line
if(voterList)
{
voterList.write(ID);
voterList.write(" ");
voterList.write(first);
voterList.write(" ");
const byte numChars = 25;
char receivedChars[numChars];
char uno;
char in;
boolean regng = false;
boolean voting = false;
boolean scanning = false;
boolean newData = false;
void setup() {
Serial.begin(9600);
Serial1.begin(9600);
}
void vote() {
Serial.print("vote");
}
void loop() {
if (Serial1.available() > 0) {
uno = Serial1.read();
if (uno == 'a') prompt();
else if (uno == 'b') reg();
else if (uno == 'c') vote();
}
}
void prompt() {
Serial.println("Enter 1 to register, or 2 to vote.");
if (Serial.available() > 0) {
in = Serial.read();
Serial1.write(in);
}
}
void recv() {
static byte ndx = 0;
char endMarker = '\n';
char rc;
while (Serial.available() > 0 || newData == false) {
if (Serial.available() > 0) {
rc = Serial.read();
if (rc != endMarker) {
receivedChars[ndx] = rc;
ndx++;
if (ndx >= numChars) {
ndx = numChars - 1;
}
}
else {
receivedChars[ndx] = '\0';
ndx = 0;
newData = true;
}
}
}
Serial1.write(receivedChars);
}
void reg() {
regng = true;
Serial1.write("r");
while (regng == true) {
if (Serial1.available() > 0) uno = Serial1.read();
if (uno == "F") {
Serial.print("First Name: ");
recv();
}
if (uno == "L") {
Serial.print("Last Name: ");
recv();
}
if (uno == "A") {
Serial.print("Age: ");
recv();
}
if (uno == "I") {
scanning = true;
while (scanning == true && Serial1.available() > 0) {
uno = Serial1.read();
if (uno == '0') Serial.println("Place finger on the scanner.");
if (uno == '1') Serial.println("Remove finger.");
if (uno == '2') Serial.println("Place finger on the scanner again.");
if (uno == '3') {
Serial.println("Scan complete!");
Serial.println("Registration successful.");
scanning = false;
regng = false;
}
if (uno == '4') {
Serial.println("Scan unsuccessful.");
scanning = false;
}
}
}
}
}
Here is my code with a few revisions... I didn't want to start a new thread on the same project so I'm going to ask here.
Initially, the Uno sends a character to the MEGA prompting it to ask to enter either a 1 or 2 serially. Upon entering a 1 to the Uno, nothing happens. To troubleshoot I printed out what the Uno was receiving, and it printed 2 backwards '?' symbols. Any idea why that could be?
mega is an object. It does not overload any operators that while can be using. So, this statement says "while the object we just used doesn't exist...". The object exists. The while loop is pointless.
void prompt() {
Serial.println("Enter 1 to register, or 2 to vote.");
if (Serial.available() > 0) {
in = Serial.read();
Serial1.write(in);
}
}
This code does NOT wait for the Uno to respond. If there IS serial data available to read at this point that available() is called, it will NOT be the response to that prompt.
Serial data transfer is asynchronous. It looks to me like you are expecting it to be synchronous. If you ARE trying to force serial data transfer into a synchronous pattern, you WILL be using while statements to wait for input.
mega is an object. It does not overload any operators that while can be using. So, this statement says "while the object we just used doesn't exist...". The object exists. The while loop is pointless.
What's this then?
class SoftwareSerial : public Stream
{
...
public:
...
operator bool() { return true; }
...
};
PaulS:
This code does NOT wait for the Uno to respond. If there IS serial data available to read at this point that available() is called, it will NOT be the response to that prompt.
Serial data transfer is asynchronous. It looks to me like you are expecting it to be synchronous. If you ARE trying to force serial data transfer into a synchronous pattern, you WILL be using while statements to wait for input.
I sorta developed a system in which one arduino would send a byte to initiate some process, with the other Arduino replying to confirm it and then execute it. I was hoping the manner in which I did that it would keep the two Arduinos in sync throughout the program. Evidently not.
What would be a more proper method to do so? T/F statements mixed with a while loop to make an arduino 'wait' for a serial message? Or make another 2 connections between the arduinos, each sending/receiving pulses and 'waiting' for those pulses to keep in sync?
Additionally, back to the OP- I really do feel as if I won't have enough dynamic storage to complete this program. Does anything else seem redundant catch your guys' eye that could potentially save memory through more efficient syntax?
What would be a more proper method to do so? T/F statements mixed with a while loop to make an arduino 'wait' for a serial message? Or make another 2 connections between the arduinos, each sending/receiving pulses and 'waiting' for those pulses to keep in sync?
If you are going to force asynchronous communications into a synchronous mode, then you need to do something like:
Serial.print("A");
while(Serial.available() == 0)
{
// Just twiddling my thumbs waiting for a response
}
// A single character came in. Deal with it...
PaulS:
The first code, as the comment says, twiddles its thumbs waiting for serial data.
The second code does NOT wait for data. It simply reads anything that might be available, or returns if there is nothing available.
The second code is NOT synchronous.
Ah, I see- So anything regarding interpreting an input should be after the while() loop?
MorganS:
uno is declared as a char. But double quotes (") means "string". There is no char which is equal to the location of the first char in the string "F".
Use single quotes (') for char. This mistake appears several times.
Just out of curiosity what happens as a result of that? Is Arduino able to convert the string to a char? Or is that something that causes broken data being sent? Good eye, thank you!
It's not able to convert because you told it not to. You specified that "F" is a string. If you told somebody to turn left and he went right, how are you going to tell them to turn right at the next street? Do you say "right" or "left"?
When you do Serial.write("A"); then it's going to send something related to the address of the string "A" in memory. It won't send an "A". However Serial.print("A"); does understand strings and will send the single character 'A'. Write is used for binary data. Print is best for human-readable text.
write(7) will send the bit pattern 00000111. Binary 7.
print(7, BIN) will send "111" because it does not print leading zeroes. That's three '1' characters in three bytes.
write('7') and print('7') and print("7") will all send the same thing: '7', which is encoded with the bit pattern 00110111 under the ASCII system.
MorganS:
It's not able to convert because you told it not to. You specified that "F" is a string. If you told somebody to turn left and he went right, how are you going to tell them to turn right at the next street? Do you say "right" or "left"?
When you do Serial.write("A"); then it's going to send something related to the address of the string "A" in memory. It won't send an "A". However Serial.print("A"); does understand strings and will send the single character 'A'. Write is used for binary data. Print is best for human-readable text.
write(7) will send the bit pattern 00000111. Binary 7.
print(7, BIN) will send "111" because it does not print leading zeroes. That's three '1' characters in three bytes.
write('7') and print('7') and print("7") will all send the same thing: '7', which is encoded with the bit pattern 00110111 under the ASCII system.
This just explained a lot for me- thank you so much!