Arduino character array serial - c++

I'm having a little bit of trouble with this bit of code here for my Arduino.
Basically, I'm trying to send in a series of characters, turn it into an character array, and use that to run the rest of the program. I'm close because I know everything is working perfectly internally, but when I boot from the serial port, the message isn't getting in.
I assume that at this point it probably is how I am constructing the array... or some oddity. It is probably just a simple error in how I put the code together, but I'm completely struck. (I was previously using a string, but because of how the Arduino works with them, it pretty much makes using them for memory purposes impossible.)
I'm using a Java program (Ardulink) to send the information into the program with a customized version I've edited. So simply put, the input has to be a series of characters, and I need it stored in an array.
void serialEvent()
{
int arrayPostion = 0;
int i;
int maxArraySize = 20;
char CharArrayInLocal[20];
while (Serial.available() && !stringComplete)
{
char inChar = (char)Serial.read();
CharArrayInLocal[arrayPostion] = inChar;
arrayPostion++;
if (inChar == '\n')
{
stringComplete = true;
}
}
for (int i = 0; i<=19; i++)
{
CharArrayIn[i] = CharArrayInLocal[i];
}
}

This worked for me,
String CharArrayInLocal[20];
String inputString = "";
boolean stringComplete = false;
int i = 0;
void serialEvent() {
while (Serial.available()) {
char inChar = (char)Serial.read();
if (inChar == '\n') {
CharArrayInLocal[i] = inputString;
i++;
stringComplete = true;
inputString = "";
}
else {
inputString += inChar;
}
}
}

Related

Making lettercheck not case sensitive

So I need to make this code be able to count the a specified letter (In this case the letter E). I've made it to the point where it counts how many times in the sentence the letter has been typed, however it is case sensitive. Right now it only counts upper-case E, which can be changed but I can't figure out how it'll read both upper and lower-case.
I've found the equalsIgnoreCase() code, however I'm not familiar with it so I don't know where to put it, how it works or if it even will work. In my case, I tried myString.equalsIgnoreCase(MyString2), in my case CharCount and CharCountLow I believe.
This is my code:
//Written sentence gets read by arduino when enter is pressed and printed into the serial monitor
//Arduino counts how many characters are in the sentence and prints out that number in serial monitor
//Arduino then counts how many times any chosen letter in the sentence is written, for example E, and then prints out that number on the monitor.
//Arduino then reads the sentence you've written and prints it backwards in serial monitor
char Message[128] = "";
char MessageInversed[128] = "";
static int CharCount;
char NextChar;
char CountChar = 'E';
char CountCharLow = 'e'; // this is what I've tried
int Counter;
boolean Done;
void setup()
{
// put your setup code here, to run once:
Serial.begin(9600);
Serial.println("<Enter your text>");
}
void loop()
{
Readmessage();
Showmessage();
}
void Readmessage()
{
static int CharCount = 0;
char EnterCheck = '\n';
while (Serial.available() > 0 && Done == false)
{
NextChar = Serial.read();
if (NextChar == CountChar || CountCharLow) // this is what I've tried
{
Counter++;
}
if (NextChar != EnterCheck)
{
Message[CharCount] = NextChar;
CharCount++;
}
else
{
InverseMessage(CharCount);
Message[CharCount-1] = '\0';
CharCount=0;
Done = true;
}
}
}
void InverseMessage(int Characters)
{
for (int InversedCharCount = 0; InversedCharCount < Characters-1; InversedCharCount++)
{
MessageInversed[Characters-2-InversedCharCount] = Message[InversedCharCount];
}
MessageInversed[Characters] = '\0';
}
void Showmessage()
{
if (Done == true)
{
Serial.print("Your message length is: ");
Serial.println(strlen(Message));
Serial.print("This is your message: ");
Serial.println(Message);
Serial.print("Your inversed message length is: ");
Serial.println(strlen(MessageInversed));
Serial.print("Your reversed message is: ");
Serial.println(MessageInversed);
if (Counter == 1)
{
Serial.print("The letter E has been typed ");
Serial.print(Counter);
Serial.println(" time");
}
else
{
Serial.print("The letter E has been typed a total of ");
Serial.print(Counter);
Serial.println(" times");
}
Serial.print("<Please enter next text>");
Done = false;
Counter = 0;
}
}
You need to check if the NextChar is the lower case letter, so it should work by typing:
if(NextChar == CountChar || NextChar == CountCharLow) {...}

How to get length of an array that is filled with input

I have asked a question here and now the code below makes the work that I expected (the work that I mentioned previously). Now I have another issue: if I write tmp[20] and if the size of the input is 20 chars, the code works. However the size of the input is not known. Therefore, there can be a maxsize, but the actual size depends on the input. How can I make this code work with every length? (yes, the code works when I write 200 inside of tmp but the size of 'message' depends on the whole array. It should be 3 chars before end and 6 chars after start).Therefore when I write 200 inside of tmp[] and the input is shorter than 200 chars, the message returns incorrectly. I think I should use dynamic memory allocation but I could not implement it to my code.
Here is my complete code:
char tmp[20] = { 0 };
int len = sizeof(tmp) / sizeof(tmp[0]);
String pack;
String command;
String Size;
String messum;
String message;
String checksum;
int Index = 0;
bool Seen = false;
void setup() {
Serial.begin(9600);
}
void loop() {
while (Serial.available() > 0) {
char received = Serial.read();
if (received == '!') {
Seen = true;
} else
if (received == '#') {
return strdup(tmp);
} else
if (Seen == true) {
if (Index < 2) {
//Serial.print("P");
pack = tmp[Index++] = received;
Serial.print(pack);
} else
if (Index < 4) {
//Serial.print("C");
command = tmp[Index++] = received;
Serial.print(command);
} else
if (Index < 6) {
//Serial.print("S");
Size = tmp[Index++] = received;
Serial.print(Size);
} else
if (Index < (len - 3)) {
//Serial.print("M");
message = tmp[Index++] = received;
Serial.print(message);
} else
if (Index < len) {
//Serial.print("C");
checksum = tmp[Index++] = received;
Serial.print(checksum);
}
}
}
return NULL;
//input: asdeyh134!123456789abcdefghtry#8647dfn
}
Anywhere you are adding characters to your array like this:
if (Seen == true) {
if (Index < 2) {
//Serial.print("P");
pack = tmp[Index++] = received;
Serial.print(pack);
You should also null terminate your string like so:
if (Seen == true) {
if (Index < 2) {
//Serial.print("P");
pack = tmp[Index++] = received;
tmp[Index] = 0;
Serial.print(pack);
That way you can use strlen to get the length of the string in the array. It will count the number of characters up to that null character.
int length = strlen(tmp);
On the next pass of the loop when you write in another character you will write it over that null and then write a new null right after that new character.

How to use length of an array in subtraction

My code below is working perfect when I write number or only len inside of it. However, I want to write(len-3) but it again return as if I write len inside of it. How can I solve it??
I get the length of the array by using:
int len = sizeof(tmp)/sizeof(tmp[0]);
The message variable is a String and received is:
char received = Serial.read();
if (Index<(len-3)){
message=tmp[Index++]=received;
Serial.print(message);
}
My aim is when I write dv35!1234567890*asdfqwertyuiopmnbvcx#asdas the code should return the part of it that is between '!' and '#' then during the if else part the code should get some parts of it. However, the last part should return until 3 chars before the array ends. but it did not work properly. it returns all the parts remaining.(As if I write only len inside of it). the length of the input is not stable so the message part changes depending on the length of the whole array. It should return 3 chars before the end.
Here is my whole code:
char tmp[200] = {0};
String pack;
String command;
String Size;
String messum;
String message;
String checksum;
int len = sizeof(tmp)/sizeof(tmp[0]);
int Index = 0;
bool Seen = false;
void setup(){
Serial.begin(9600);
}
void loop(){
while (Serial.available() > 0){
char received = Serial.read();
if (received == '!'){
Seen = true;
}
else if (received == '#'){
return strdup(tmp);
}
else if (Seen == true){
if(Index<2){
//Serial.print("P");
pack=tmp[Index++] = received;
Serial.print(pack);
}
else if(Index<4){
//Serial.print("C");
command=tmp[Index++] = received;
Serial.print(command);
}
else if(Index<6){
//Serial.print("S");
Size=tmp[Index++] = received;
Serial.print(Size);
}
else if (Index<(len-3)){
Serial.print("M");
message=tmp[Index++]=received;
Serial.print(message);
}
}
}
return NULL;
//input: dv35!1234567890*asdfqwertyuiopmnbvcx#asdas
}
there is no need of most of it.
You define the variable tmp in the global and it has constant length. You do not need to calculate the length of it.
For the char array sizeof(char_array) gives you the length of the array as sizeof(char) is by definition 1
Use the correct types. for the sizes use size_t not int

Adding the next character on a string C++

I did get the next character on a string (hello-->ifmmp) but in the case of hello* i want to be able to still display the * as the exception, it can be also a number but i guess it does not matter because is not in the alphabet.
this is my code, Where should be the else if?
There is another option but i dont find it optimized, it is to add inside the first for loop this:
string other="123456789!##$%^&*()";
for(int z=0;z<other.length();z++)
{
if(str[i]==other[z])
str2+=other[z];
}
Then this is the main code;
int main()
{
string str = "hello*";
string str2="";
string alphabet = "abcdefghijklmnopqrstuvwxyz";
for(int i=0;i<str.length();i++)
{
for(int j=0;j<alphabet.length();j++)
{
if(str[i]==alphabet[j])
{
str2+=alphabet[j+1];
}
}
}
cout<<str2<<endl;
return 0;
}
I like functions. They solve a lot of problems. For example, if you take the code you already have, paste it into a function, and give it a little tweak
char findreplacement(char ch, const std::string & alphabet)
{
for (int j = 0; j < alphabet.length(); j++)
{
if (ch == alphabet[j])
{
return alphabet[(j+1) % alphabet.length()];
// return the replacement character
// using modulo, %, to handle wrap around z->a
}
}
return ch; // found no replacement. Return original character.
}
you can call the function
for (int i = 0; i < str.length(); i++)
{
str2 += findreplacement(str[i], alphabet);
}
to build str2. Consider using a range-based for here:
for (char ch: str)
{
str2 += findreplacement(ch, alphabet);
}
It's cleaner and a lot harder to screw up.
There is a function isalpha in the standard library which is very useful for classification.
You could do something like this.
(This kind of exercise usually assumes the ASCII encoding of the English alphabet, and this is a very ASCII-specific solution. If you want a different alphabet or a different character encoding, you need to handle that yourself.)
#include <cctype>
#include <string>
#include <iostream>
int main()
{
std::string str = "Hello*Zzz?";
std::string str2;
for (char c: str)
{
if (std::isalpha(c))
{
c += 1;
if (!std::isalpha(c))
{
// Went too far; wrap around to 'a' or 'A'.
c -= 26;
}
}
str2 += c;
}
std::cout << str2 << std::endl;
}
Output:
Ifmmp*Aaa?

How do I store a stream of characters in an array?

I have a stream of characters coming over the serial port like this;
FILE1,FILE2,FILE3,
I'm trying to read them in like this;
char* myFiles[20];
boolean done = false;
int fileNum = 0;
int charPos = 0;
char character;
while (!done)
{
if (Serial.available())
{
character = Serial.read();
if ((character == '\n') || (character == '\r'))
{
done = true;
}
else if (character == ',')
{
myFiles[fileNum][charPos] = '\0';
fileNum++;
charPos = 0;
}
else
{
myFiles[fileNum][charPos] = character;
charPos++;
}
}
}
when I try to print the first value like this;
Serial.println(myFiles[0]);
i get a continuous stream of characters.
What am i doing wrong?
What you are doing wrong is not allocating any memory for your strings.
Here's one way to do this
#include <vector>
#include <string>
std::vector<std::string> myFiles;
std::string file;
bool done = false;
char character;
while (!done)
{
if (Serial.available())
{
character = Serial.read();
if ((character == '\n') || (character == '\r'))
{
done = true;
}
else if (character == ',')
{
myfiles.push_back(file);
file = "";
}
else
{
file += character;
}
}
}
Serial.println(myFiles[0].c_str());
Since you are programming in C++ you should learn how to use std::vector and std::string, they will save you a lot of grief.
If std::vector and std::string are not available to you (apparently so on Arduino) then the quick hack would be to preallocate a fixed amount of memory for your strings by replacing
char* myFiles[20];
with
char myFiles[20][100];