I have a circuit that accepts data (an array of characters to be specific) via bluetooth from my android program.
now, what I want to do is: reprogram my microcontroller, I wish to filter or extract a series of characters from the array that my micrcontroller receives.
My android passes these three kinds of char arrays:
1. red#ILOVEYOU
2. blue#ILOVEYOULALALA
3. green#ILOVEDIANAROSECUSTODIO:)
I want to extract the red# or blue# or green# and transfer it to other variable. my phone sends a '#' in the end of each colors because I guess it will make the extraction easier.
char Comp(char* This){
while(Serial.available() > 0) // Don't read unless
// there you know there is data
{
if(index < 99){
inChar = Serial.read(); // Read a character
if(inChar == '#'){
}
inData[index] = inChar; // Store it
index++; // Increment where to write next
inData[index] = '\0'; // Null terminate the string
}
}
if(strcmp(inData,This) == 0){
for(int i=0;i<19;i++){
inData[i]=0;
}
index=0;
return(0);
}
else{
return(1);
}
}
This is my code in arduino. You see, it receives one character at a certain very little time and then adds it to a char array variable.
You can use strtok() function in c.
Related
I am writing a program that to Define a new int array of 500 integers to store the input data,also Convert and store the input integers to the array and Display the size of the input data and display the input data as well.
I face the problem that i can't show my input data correctly on the Serial Monitor.For example if i input 123 it will show input data = 3 integers and my input data will become ⸮.But i want myint[0]=123 not myint[0]=1, myint[1]=2, myint[2]=3 so the size should be just count for 1 integers.
I also cannot show what i input the integer on the Serial Monitor.Also how can i not count the space as the size of input data for example:if i input "123 234" it will just show "Size of input data = 2 integers"
This is the Serial Monitor showing when i input 123:
Please input
Size of input data = 3 integers
⸮
Please input
Here's my code:
int myint[499] ; // this is an array
char input;
int i;
void setup() {
// Initialize serial and wait for port to open:
Serial.begin(115200);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
}
void loop() {
while (Serial.available() > 0) {
input = Serial.read();
if (input != '\n') {
myint[i++] = input; // last character is newline
myint[i] = 0; // string array should be terminated with a zero
} else{
input = Convertinteger(input);
myint[i++] = input;
myint[i] = 0;
Serial.println("Please input");
Serial.print("Size of input data = ");
Serial.print(i-1);
Serial.print(" integers");
Serial.println("");
Serial.print(input);
Serial.println("");
Serial.println("");
Serial.println("Please input");
i = 0;
}
}
}
int Convertinteger(char x) {
if (x <= 0x39 && x >= 0x30)
return (x - 0x30);
This line:
Serial.print(input);
will simply print the value in the input variable. The input variable is a char containing \n since that's what the if else was testing for earlier in the code. If you are wanting to print all three values in your array you will need an too loop through the array printing each value.
Re-reading this I see other issues. You will need two separate arrays. One should be an array of characters (char). That would act as a buffer of each character as it is received. Then when you receive the newline ('\n') you should put a 0 in the character buffer instead of the newline. So if you press the keys '1', '3', '8' you will have created the string "138". Then that is your input to Convertinteger. At which point for testing I would print both the input string and the integer output.
Take the output from Convertinteger and store it in your second array which will be an array of int. You'll need some way to indicate that your done entering numbers. Maybe just hit enter without entering any numbers. So if after the newline is entered if the first byte of the string is 0 (which is one way to detect an empty string) break out of the loop. Then if you counted 5 number entries you loop 5 times printing them.
I was work with system, that read some symbols from the specific keyboard, pass it to the ATmega8, and then pass it to the display one-by-one(this step work correctly), but if I want to show all symbols array, I discovered that the dynamic array on first position save null, on the second save empty symbol, and the subsequent characters saved correctly. I don't see any mistakes in code, so I need a help.
This code function must return the 4-elements char array of symbols reading serial from the keyboard.
char* askPass(void){
int i;
char key;
#define PS 4
char* pass = (char*)calloc(PS, sizeof(char));
clear:
lcd_clear();
lcd_gotoxy(0, 0);
lcd_puts("Enter the password:");
lcd_gotoxy(0, 1);
lcd_puts(">>");
free(pass);
pass = (char*)calloc(0, sizeof(char));
for (i=0;i<PS;i++) pass[i] = '';
for (i=0; i<PS; i++) {
key = '-';
key = readKey();
lcd_gotoxy(3+i, 1);
if (key == 'C') {
goto clear;
} else if (key == '-'){
lcd_putchar('|');
delay_ms(10);
lcd_gotoxy(3+i, 1);
lcd_putchar(' ');
delay_ms(10);
lcd_gotoxy(3+i, 1);
i--;
} else {
pass = (char*)realloc(pass, i*sizeof(char));
*(pass+i) = key;
lcd_putchar(*(pass+i));
delay_ms(20);
}
}
/// there is an error:
/// serial input: 1234
/// lcd output: !* 34!
/// correct output: !1234!
lcd_gotoxy(0,2);
lcd_puts("!");
for (i=0; i<PS; i++) {
if (!(*(pass+i))) lcd_putchar('*');
else lcd_putchar(*(pass+i));
}
lcd_puts("!");
// end error block
return pass;
} // can't return correct array value
/*
All tests show this:
Serial input word: abcd
Output: !* cd!
Correct output: !abcd!
*/
You start my allocating 4 bytes with:
char* pass = (char*)calloc(PS, sizeof(char));
Then you call free(pass) before you even use the allocated data, only to then allocates zero bytes with:
pass = (char*)calloc(0, sizeof(char));
If makes no sense to allocate only to free without using the allocation, or to allocate zero bytes. The act of allocating zero bytes is undefined, but nothing good or useful will happen by attempting to write to such an allocation as you do.
Continuously reallocation to add one byte at a time is ill-advised also. It would be better to allocate a buffer of a reasonable length to start with and if you need to extend, extend by a number of characters in on chunk.
It is unclear in any case why you are dynamically allocating and reallocating to allow input of an arbitrary number of characters that you are not using. It would be simpler and more deterministic, to simply accept the four characters in a fixed length array and discard any extraneous input.
There is no such thing as an "empty character", calloc already initialised the allocation to zero (a nul character).
I am pretty certain this code has many other issues, but it is had to determine what you are trying to do in order to advise; you would well to use a debugger.
I've been searching for ways of emptying a char array in C/C++. I have come up with this code:
char testName[20];
for(int i = 0; i < sizeof(testName); ++i)
{
testName[i] = (char)0;
}
It has been working for a while now but when I try to strlenthe result is always two more than the typed in word. For instance I input the word dog the output would be five. Why is that so? Is my char array not cleared?
Here is my code:
char testName[20];
void loop()
{
if(Serial.available())
{
Serial.println("Waiting for name...");
index = 0;
for(int i = 0; i < sizeof(testName); ++i)
{
testName[i] = (char)0;
}
while(Serial.available())
{
char character = Serial.read();
testName[index] = character;
index++;
}
Serial.print("Name received: ");
Serial.println(testName);
Serial.print("The sentence entered is ");
Serial.print(strlen(testName));
Serial.println(" long");
delay(1000);
}
delay(1000);
}
Screenshot of the output:
Output as text:
Name received: dog
The sentence entered is 5 characters long
Don't use C style arrays in modern C++. When you require a fixed size array, use std::array instead. From a memory storage point of view, they are identical.
You can then clear the array with: myarray.fill('\0')
If your definition of "emptying char array" is set all elements of an array to zero, you can use std::memset.
This will allow you to write this instead of your clear loop:
const size_t arraySize = 20; // Avoid magic numbers!
char testName[arraySize];
memset(&(testName[0]), 0, arraySize);
As for "strange" results of strlen():
strlen(str) returns "(...) the number of characters in a character array whose first element is pointed to by str up to and not including the first null character". That means, it will count characters until it finds zero.
Check content of strings you pass to strlen() - you may have white characters there (like \r or \n, for example), that were read from the input stream.
Also, an advice - consider using std::string instead of plain char arrays.
Small note: memset() is often optimized for high performance. If this in not your requirement, you can also use std::fill which is a more C++ - like way to fill array of anything:
char testName[arraySize];
std::fill(std::begin(testName), std::end(testName), '\0');
std::begin() (and std::end) works well with arrays of compile-time size.
Also, to answer #SergeyA's comment, I suggest to read this SO post and this answer.
Yet another quick way of filling an array with zeroes, in initialization only:
char testName[20] = {};
same as
char testName[20] = {0};
Since it is a C99 feature, compiler could complain with the following
warning: ISO C forbids empty initializer braces
More here.
Anyway, looking at the OP code, there's no need at all of initializing/filling the array, it could be better like this:
#define MAX_LENGTH 20
char testName[MAX_LENGTH];
void loop()
{
if(Serial.available())
{
Serial.println("Waiting for name...");
index = 0;
while(Serial.available())
{
if(index < MAX_LENGTH)
testName[index++] = Serial.read();
}
if(index < MAX_LENGTH)
{
testName[index] = 0;
Serial.print("Name received: ");
Serial.println(testName);
Serial.print("The sentence entered is ");
Serial.print(strlen(testName));
Serial.println(" long");
}
else
Serial.print("Name too long ...");
delay(1000);
}
delay(1000);
}
For posterity. The OP example is an Arduino sketch. Assuming here that the input is taken through the built-in Serial Monitor of the Arduino IDE. At the bottom of the Serial Monitor window is a pop-up menu where the line ending can be selected as:
No line ending
newline
Carriage return
Both NL & CR
Whatever option is selected in this menu is appended to whatever is entered in the box at the top of the Serial Monitor when the Send button is clicked or the return key is hit. So the extra two characters are most certainly the result of having the "Both NL & CR" menu option selected.
Picking the "No line ending" option will solve the problem.
FWIW, in this application, the array does not need to be "cleared". Just append a '\0' char to the last char received to make it a C-string and all will be good.
We are trying to initialize a character array but it we get an error saying that we can not as we can not mix integers and chars, but we dont have have integers initialized.
thanks in advance
void setup()
{
Serial.begin(9600); //Set the serial monitor.
lcd.begin(16, 2); //Set the LCD
}
char line1 [5] = {0};
char line2 [] = {0};
void loop()
{
if (Serial.available() > 0) { //If the serial monitor is open it will read a value.
line1 = Serial.read();
delay(10);
Serial.print(line1);
lcd.print(line1);
}
}
I am not an arduino guy, but I did stay at a Holiday Inn last night with access to Google :)
http://arduino.cc/en/Serial/Read
Serial.read() returns a single byte (as an int). You're trying to assign that to a char array.
You can't do that. You can assign something to a specific element in an array:
line1[0] = 'c';
for example, but you can't assign to an array itself.
It seems like you're looking for Serial.readBytes()
http://arduino.cc/en/Serial/ReadBytes
Which would look like:
Serial.readBytes(line1, 5);
in your case where 5 is the length of your buffer (array). This would read (at most) 5 bytes into your line1 buffer.
Edit to add: That being said, it appears arduino's "C-Like" language is very much like C in that it expects "Strings" (char arrays) to be null terminated when passing them to Serial.print(). The advice above doesn't do that and in fact would cause problems.
What you would need to do is read up to one byte less than the length of your array, and then null terminate the "string" using the number of bytes actually read which is what bytesRead() returns to you (arrays are zero indexed):
int numBytesRead = 0;
...
numBytesRead = Serial.readBytes(line1, 4);
line1[numBytesRead] = '\0';
Serial.print(line1);
Option B is to do as I originally mentioned, but loop and print one byte at a time from your line1 array using the index:
int numBytesRead = 0;
numBytesRead = Serial.readBytes(line1, 5);
int i;
for (i = 0; i < numBytesRead; i++) {
Serial.print(line1[i]);
}
According to the docs Serial.print() automagically knows to send a single byte/char when that's all that's passed to it.
I am trying to read a serial response from a hardware device. The string I read is long and I only need a portion of it. To get to portion of the string I want I use std::string.substr(x,y); . The problem I run into however is sometimes I get an exception error because the buffer I am reading from doesn't have y characters. Here is the code I use now to read values:
while(1)
{
char szBuff[50+1] = {0};
char wzBuff[14] = {"AT+CSQ\r"};
DWORD dZBytesRead = 0;
DWORD dwBytesRead = 0;
if(!WriteFile(hSerial, wzBuff, 7, &dZBytesRead, NULL))
std::cout << "Write error";
if(!ReadFile(hSerial, szBuff, 50, &dwBytesRead, NULL))
std::cout << "Read Error";
std:: cout << szBuff;
std::string test = std::string(szBuff).substr(8,10);
std::cout << test;
Sleep(500);
I am issuing the command "AT+CSQ". This returns:
N, N
OK
It returns two integer values seperated by a comma followed by a new line, followed by "OK".
My question is, how can I make sure I read all values from the serial port before grabbing a substring? From what I understand, the last character received should be a new line.
The interface of your ReadFile function seems to provide you with the number of bytes read. If you know the length that is expected, you should loop trying reading from the file (probably port descriptor) until the expected number of bytes is read.
If the length of the response is not known, you might have to read and check in the read buffer whether the separator token has been read or not (in this case your protocol seems to indicate that a new-line can be used to determine EOM --end of message)
If you can use other libraries, I would consider using boost::asio and the read_until functionality (or the equivalent in whatever libraries you are using). While the code to manage this is not rocket science, in most cases there is no point in reinventing the wheel.
As you said yourself in the last line, you know that the terminator for the response is a new line character. You need to read from the serial until you receive a new line somewhere in the input. Everything you received from the previous new line to the current new line is the response, with everything after the current new line is part of the next response. This is achieved by reading in a loop, handling each response as it is discovered:
char* myBigBuff;
int indexToBuff = 0;
int startNewLine = 0;
while (ReadFile(hSerial, myBigBuff + indexToBuff, 100, &dwBytesRead, NULL))
{
if (strchr(myBigBuff, '\n') != NULL)
{
handleResponse(myBigBuff + startNewLine, indexToBuff + dwBytesRead);
startNewLine = indexToBuff + dwBytesRead;
}
// Move forward in the buffer. This should be done cyclically
indexToBuff += dwBytesRead;
}
This is the basic idea. You should handle the left overs characters via any way you choose (cyclic buffer, simple copy to a temp array, etc.)
You should use ReadFile to read a certain amount of bytes per cycle into your buffer. This buffer should be filled until ReadFile reads 0 bytes, you have reached your \n or \r\n characters, or filled your buffer to the max.
Once you have done this, there would be no need to substr your string and you can iterate through your character buffer.
For example,
while (awaitResponse) {
ReadFile(hSerial, szBuff, 50, &dwBytesRead, NULL);
if (dwBytesRead != 0) {
// move memory from szBuff to your class member (e.g. mySerialBuff)
} else {
// nothing to read
if (buffCounter > 0) {
// process buffer
}
else {
// zero out all buffers
}
}
}
Old question, but I modified #Eli Iser code to:
while (ReadFile(hSerial, myBigBuff + indexToBuff, 1, &dwBytesRead, NULL)) {
if (strchr(myBigBuff, '-') != NULL || dwBytesRead < 1)
break;
// Move forward in the buffer. This should be done cyclically
indexToBuff += dwBytesRead;
}
if (indexToBuff != 0) {
//Do whatever with the code, it received successfully.
}