I am new programming.
I am trying to convert integers to boolean in arduino, but I always get 1.
Help me please:
/////////////////////////////////
boolean booleanValue;
int val;
void setup() {
Serial.begin(9600);// connect to the serial port
}
void loop () {
if (Serial.available()) {
val = Serial.read();//// read the serial port
boolean booleanValue = !!val;
Serial.println(booleanValue);
}
}
You need to use Serial.parseInt() instead of Serial.read().
Serial.read() returns the bit pattern for the input byte, hex 30 for the character "0". It would return 0 if the input were a null byte, not a digit, letter etc.
Alternatively, you could check for the input being exactly 0x30, treat that as false, and treat all other inputs as true.
You should try to isolate the code you suspect, and make sure you know exactly what input is it working with. In this case, inserting Serial.println(val,HEX); immediately after the read would have told you the problem was in how you were reading, rather than in the conversion.
Related
The characters I got for Arduino BLE characteristics reading are always tailed with some random characters. For example, the printing should ends with "test string" but it actually print out "test string !" The tailing string is randomized based on different string being sent.
Any suggestions for resolving this issue?
The code for reading character is the following:
void incomingCharacteristicWritten(BLEDevice central, BLECharacteristic characteristic) {
byte value[characteristic.valueLength()];
incomingDataCharacteristic.readValue(value, characteristic.valueLength());
Serial.print("Characteristic event, written: ");
Serial.print((char *) value);
}
The problem is that readValue() writes to a buffer of bytes, which is NOT the same as a null-terminated C string. So by simply casting the buffer to a char * and printing it, the print() function will stop when it encounters the first null character. This may be soon or late, depending on what arbitrary contents you have in memory. This explains the random characters you've observed.
To fix this, either print the bytes one at a time in a loop, convert it to a C++ string, or make sure to null-terminate it.
For example, the following should work:
void incomingCharacteristicWritten(BLEDevice central, BLECharacteristic characteristic) {
int length = characteristic.valueLength();
byte value[length + 1]; // one byte more, to save the '\0' character!
incomingDataCharacteristic.readValue(value, length);
value[length] = '\0'; // make sure to null-terminate!
Serial.print("Characteristic event, written: ");
Serial.print((char *) value);
}
I'm trying to collect data from a simple multimeter circuit, but instead of returning numbers my serial port is just outputting random Unicode symbols.
Here's my code:
void setup() {
pinMode(2, INPUT);
Serial.begin(1200);
int prevVal = 0;
int timeVar = 0;
}
void loop() {
int digisensorVal = digitalRead(2);
int anasensorVal = analogRead(2) * 100;
Serial.print("D" + digisensorVal);
Serial.print(",");
Serial.println("A" + anasensorVal);
delay(250);
}
And here's a sample of the output:
⸮L/⸮U⸮⸮⸮⸮⸮?⸮⸮⸮w⸮e⸮⸮⸮⸮1⸮⸮⸮⸮}⸮J⸮⸮⸮⸮⸮oޝ⸮Y⸮⸮⸮|s⸮⸮}⸮⸮⸮⸮⸮⸮⸮є6x⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮y[⸮⸮⸮⸮⸮?⸮v⸮=⸮⸮⸮-⸮^⸮Y_z⸮⸮d⸮⸮⸮%ܿjV⸮~O⸮⸮G⸮⸮⸮⸮e⸮⸮U⸮⸮~+0⸮⸮⸮hh⸮s⸮
⸮c⸮⸮⸮+⸮⸮io3:⸮5kλϣ
,⸮g⸮⸮⸮⸮⸮>⸮⸮
⸮yꨛ⸮v⸮N⸮⸮⸮=⸮⸮=⸮⸮⸮l⸮⸮g⸮g⸮⸮⸮⸮⸮s⸮U⸮⸮⸮⸮⸮⸮=⸮ܳt⸮⸮⸮}⸮⸮'⸮˾⸮k⸮⸮⸮⸮⸮⸮⸮{⸮ᦒ⸮⸮⸮⸮ϓ߿gVp⸮⸮⸮⸮Y⸮⸮O⸮/F⸮~⸮⸮⸮⸮q4⸮⸮_f⸮⸮⸮⸮⸮I|P⸮⸮⸮NE⸮~u⸮7⸮⸮⸮⸮g⸮⸮G~⸮⸮⸮⸮__#⸮⸮⸮⸮⸮⸮⸮C⸮⸮⸮k⸮T⸮o/⸮t^⸮~⸮{}⸮w⸮⸮⸮⸮'h=⸮ϸ~⸮⸮⸮⸮⸮⸮⸮?⸮s⸮s⸮l⸮o5⸮^⸮⸮⸮w9{]⸮⸮q~⸮⸮⸮,⸮⸮⸮c⸮2_⸮⸮⸮⸮o6k)ޏ⸮k⸮ׇ⸮i⸮⸮m⸮⸮:⸮⸮⸮⸮|⸮⸮??⸮⸮⸮⸮3⸮⸮⸮⸮⸮⸮⸮⸮⸮^⸮⸮ڏ⸮⸮⸮⸮l⸮⸮⸮⸮⸮⸮H⸮~⸮>⸮⸮z⸮⸮⸮⸮⸮OwM;⸮⸮l⸮⸮
⸮sr⸮S⸮⸮}⸮⸮⸮⸮ׂٶ⸮⸮~⸮{⸮⸮]⸮⸮⸮⸮⸮⸮⸮⸮i⸮⸮⸮⸮⸮[⸮⸮⸮⸮⸮Nz⸮⸮⸮⸮⸮k⸮⸮⸮⸮⸮g⸮k⸮⸮⸮i3ɵ⸮⸮~⸮⸮⸮⸮⸮]⸮2ϪWކ⸮i>⸮gu⸮⸮ӵ⸮?⸮̥⸮⸮m⸮⸮|⸮⸮⸮⸮Wɓ⸮⸮⸮[⸮⸮O㠑_⸮⸮⸮⸮⸮⸮⸮⸮⸮/⸮M⸮⸮_⸮⸮gwF⥷⸮⸮yn⸮P⸮⸮-⸮⸮⸮N⸮⸮⸮=⸮⸮⸮⸮⸮⸮⸮>J⸮}⸮⸮&⸮⸮⸮C⸮HG翎⸮/⸮⸮⸮⸮}⸮⸮⸮^⸮⸮,⸮)[⸮⸮⸮⸮⸮⸮У⸮⸮}⸮ޯ⸮⸮⸮⸮7⸮⸮⸮⸮ó⸮U:~⸮⸮ns⸮⸮z⸮⸮n⸮⸮G|ӳ⸮⸮}⸮⸮L⸮~⸮⸮KI⸮⸮G⸮⸮⸮⸮⸮⸮ӏ⸮⸮⸮⸮u6⸮W⸮⸮⸮⸮Ӊ۾⸮⸮9⸮zVΆ럿⸮⸮⸮ۘ⸮⸮T⸮<⸮⸮⸮⸮⸮⸮⸮/⸮⸮⸮⸮xG~⸮V⸮⸮u+N⸮⸮ݫ⸮⸮⸮cv~⸮⸮⸮W⸮
Serial.println("A" + anasensorVal);
This needs to be done in two lines. You're adding the sensor value to a pointer value and sending whatever garbage is pointed to at the memory location that adds up to. And it definitely isn't what you want. This isn't Java. You can't just add strings with a + like that.
With
Serial.println("A" + anasensorVal);
you are not actually printing number, but a string from some place in the memory starting at the address of "A" + value of "anasensorVal" and thus you will get some garbage.
You are trying to add an integer to a pointer to char(and likely move beyond the end of the string "A"), that's not what you want.
The usual way of formating output on arduino:
Serial.print("A");
Serial.println(anasensorVal);
Alternatively, you can define a stream operator for the Serial object, see https://playground.arduino.cc/Main/StreamingOutput how to do that and then format output like this:
Serial << "A" << anasensorVal;
Adding an int type and character type in Serial.print is messing up the format of the data you are trying to print to the monitor.
I'm trying to receive a number from an Arduino as an integer in C++. The full code is below:
#define STRICT
#include <tchar.h>
#include <windows.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "Serial.h"
#include <boost\lexical_cast.hpp>
enum { EOF_Char = 27 };
int __cdecl _tmain(int /*argc*/, char** /*argv*/)
{
CSerial serial;
LONG lLastError = ERROR_SUCCESS;
// Attempt to open the serial port (COM4)
lLastError = serial.Open(_T("COM4"), 0, 0, false);
// Setup the serial port (9600,8N1, which is the default setting)
lLastError = serial.Setup(CSerial::EBaud9600, CSerial::EData8, CSerial::EParNone, CSerial::EStop1);
// Register only for the receive event
lLastError = serial.SetMask(CSerial::EEventBreak |
CSerial::EEventCTS |
CSerial::EEventDSR |
CSerial::EEventError |
CSerial::EEventRing |
CSerial::EEventRLSD |
CSerial::EEventRecv);
// Use 'non-blocking' reads, because we don't know how many bytes
// will be received. This is normally the most convenient mode
// (and also the default mode for reading data).
lLastError = serial.SetupReadTimeouts(CSerial::EReadTimeoutNonblocking);
// Keep reading data, until an EOF (CTRL-Z) has been received
bool fContinue = true;
do
{
// Wait for an event
lLastError = serial.WaitEvent();
// Save event
const CSerial::EEvent eEvent = serial.GetEventType();
// Handle data receive event
if (eEvent & CSerial::EEventRecv)
{
// Read data, until there is nothing left
DWORD dwBytesRead = 0;
char szBuffer[101];
do
{
// Read data from the COM-port
lLastError = serial.Read(szBuffer, sizeof(szBuffer) - 1, &dwBytesRead);
if (dwBytesRead > 0)
{
// Finalize the data, so it is a valid string
szBuffer[dwBytesRead] = '\0';
// Display the data
printf("%s", szBuffer);
// Check if EOF (CTRL+'[') has been specified
if (strchr(szBuffer, EOF_Char))
fContinue = false;
}
} while (dwBytesRead == sizeof(szBuffer) - 1);
}
} while (fContinue);
// Close the port again
serial.Close();
return 0;
}
I have my Arduino constantly sending out the number 51. This code works fine and consistently displays "51". However, I want an int to manipulate in C++.
First I added
std::stringstream str(szBuffer);
int tester;
str >> tester;
printf("My number is: %d\n", tester+1);
right after
printf("%s", szBuffer);
A typical result looks like:
51My number is: 52
51My number is: 52
51My number is: 52
51My number is: 52
51My number is: 52
5My number is: 6
1My number is: 2
After doing it perfectly 5 or 6 times, the output always separates the incoming digits once or twice in a row (I haven't been able to find a specific pattern yet, but it's always 5-6 and 1-2).
My other attempt was to use the boost library:
int tester = boost::lexical_cast<int>(szBuffer);
printf("My number is: %d\n", tester);
right after
printf("%s", szBuffer);
and I get the same result (1-2 errors after 5-6 correct ones). I don't think the Arduino is sending bad data, since just a
printf("%s", szBuffer);
will never deviate from the number it's supposed to be. Could the conversion be messing up the receiving of data? Thanks.
EDIT: The Arduino code is:
void setup() {
Serial.begin(9600); // same as in your c++ script
}
void loop() {
Serial.print(51);
delay(1000);
}
With serial ports, there is no mechanism where a transmitter can inform a receiver how many bytes were transmitted as a block. I.e. there's no "hidden" marker where Serial.print(51); tells the receiver that it sent two characters as one number. You have to add some kind of indication (spaces, commas, line ends, initial byte counts, whatever) to your serial protocol.
Because of this, the number of characters you get from serial.Read depends on the number of characters you asked it to read (the second parameter) and how many characters are in the serial port's receive buffer, whichever is smaller. Most of the time, it seems the Arduino sends both digits before you call serial.Read, but sometimes it only gets one out in time... and the second is read the next time through the loop.
So let's assume you decided to use line ends to separate your numbers. All you have to do on the Arduino end is change to Serial.println(51);. The receive end is a little more complex.
I don't know what your serial library has in it. Most have some kind of "read line" function, and you would just replace the serial.Read call with something like:
serial.Readline(szBuffer, sizeof(szBuffer) - 1);
and it will take care of null-terminating the output. If it doesn't take care of null-termination, you'll need to find the line end and change it to a \0 yourself. From this point on, your code will work fine, because the serial.Readline function will block until it gets the whole line.
If you don't have a "read line" or at least a "read until this character" function, it's a bit harder. You have to repeatedly call serial.Read, moving through your buffer, until you see the line end character. Further, you run the risk of reading part or all of the next line, so you can't just discard all the data you read when you're done reading the number; you have to move teh data in the buffer so the next line's data (and further) is at the start of the buffer.
If you're using Boost (are you? it has no CSerial that I see), it looks like it has a read_until function. This takes three parameters: the stream you're reading from, a stream buffer to store the data in, and something to stop on. In this case, the stream buffer for storage is the one in your std::stringstream:
std::stringstream buffer;
size_t chars = boost::asio::read_until(serial, buffer.rdbuf(), '\n');
if(chars == 0) return;
int tester;
buffer >> tester;
printf("My number is: %d\n", tester+1);
I have an arduino board that is connected to a sensor. From Arduino IDE serial monitor, I see the readings are mostly 160, 150, etc. Arduino has a 10 bit ADC, so I assume the readings range from 0 to 1024.
I want to fetch that readings to my computer so that I can do further processing. It must be done this way up to this point. Now, I wrote a c++ program to read serial port buffer with Windows APIs (DCB). The transfer speed of the serial ports are set to 115200 on both the Arduino IDE and the c++ program.
I will describe my problem first: Since I want to send the readings to my computer, I expect the data looks like the following:
124
154
342
232
...
But now it looks like
321
43
5
2
123
...
As shown, the data are concatenated. I knew it because I tried to display them with [], and the data are truly messed up.
The section of the code that is doing the serial port reading on the computer is as here:
// Read
int n = 10;
char szBuff[10 + 1] = {0};
DWORD dwBytesRead = 0;
int i;
for (i = 0; i < 200; i++){
{
if(!ReadFile(hSerial, szBuff, n, &dwBytesRead, NULL)){
//error occurred. Report to user.
printf("Cannot read.\n");
}
else{
printf("%s\n" , szBuff);
}
}
}
The Arduino code that's doing the serial port sending is:
char buffer [10] = { 0 };
int analogIn = 0;
int A0_val = 0;
void setup() {
Serial.begin(115200);
}
void loop() {
A0_val = analogRead(analogIn);
sprintf(buffer, "%d", A0_val);
Serial.println(buffer);
}
I suspect that the messing up of the data is caused by different size of the buffer used to transmit and receive data in the serial port. What is the good suggestion for the size of the buffer and even better method to guarantee the successful transmission of valid data?
Thanks very much!
Your reciever code cannot assume a single read from the serial port will yield a complete line (i.e. the 2 or 3 digits followed by a '\n' that the arduino continuously sends).
It is up to the receiver to synthetize complete lines of text on reception, and only then try to use them as meaningful numbers.
Since the serial interface is extremely slow compared with your average PC computing power, there is little point in reading more than one character at a time: literally millions of CPU cycles will be spent waiting for the next character, so you really don't need to react fast to the arduino input.
Since in that particular case it will not hinder performances in the slightest, I find it more convenient to read one character at a time. That will save you the hassle of moving bits of strings around. At least it makes writing an educational example easier.
// return the next value received from the arduino as an integer
int read_arduino (HANDLE hserial)
{
char buffer[4]; // any value longer than 3 digits must come
// from a faulty transmission
// the 4th caracter is used for a terminating '\0'
size_t buf_index = 0; // storage position of received characters
for (;;)
{
char c; // read one byte at a time
if (!ReadFile(
hSerial,
&c, // 1 byte buffer
1, // of length 1
NULL, // we will read exactly one byte or die trying,
// so length checking is pointless
NULL)){
/*
* This error means something is wrong with serial port config,
* and I assume your port configuration is hard-coded,
* so the code won't work unless you modify and recompile it.
* No point in keeping the progam running, then.
*/
fprintf (stderr, "Dang! Messed up the serial port config AGAIN!");
exit(-1);
}
else // our read succeded. That's a start.
{
if (c == '\n') // we're done receiving a complete value
{
int result; // the decoded value we might return
// check for buffer overflow
if (buf_index == sizeof (buffer))
{
// warn the user and discard the input
fprintf (stderr,
"Too many characters received, input flushed\n");
}
else // valid number of characters received
{
// add a string terminator to the buffer
buffer[buf_index] = '\0';
// convert to integer
result = atoi (buffer);
if (result == 0)
{
/*
* assuming 0 is not a legit value returned by the arduino, this means the
* string contained something else than digits. It could happen in case
* of electricval problems on the line, typically if you plug/unplug the cable
* while the arduino is sending (or Mr Fluffy is busy gnawing at it).
*/
fprintf (stderr, "Wrong value received: '%s'\n", buffer);
}
else // valid value decoded
{
// at last, return the coveted value
return res; // <-- this is the only exit point
}
}
// reset buffer index to prepare receiving the next line
buf_index = 0;
}
else // character other than '\n' received
{
// store it as long as our buffer does not overflow
if (buf_index < sizeof (buffer))
{
buffer[buf_index++] = c;
/*
* if, for some reason, we receive more than the expected max number of
* characters, the input will be discarded until the next '\n' allow us
* to re-synchronize.
*/
}
}
}
}
}
CAVEAT: this is just code off the top of my head. I might have left a few typos here and there, so don't expect it to run or even compile out of the box.
A couple of basic problems here. First, it is unlikely that the PC can reliably keep up with 115,200 baud data if you only read 10 bytes at a time with ReadFile. Try a slower baud rate and/or change the buffer size and number of bytes per read to something that will get around 20 milliseconds of data, or more.
Second, after you read some data put a nul at the end of it
szBuf[dwBytesRead] = 0;
before you pass it to printf or any other C string code.
Friends
I want to integrate the following code into the main application code. The junk characters that come populated with the o/p string dumps the application
The following code snipette doesnt work..
void stringCheck(char*);
int main()
{
char some_str[] = "Common Application FE LBS Serverr is down";
stringCheck(some_str);
}
void stringCheck(char * newString)
{
for(int i=0;i<strlen(newString);i++)
{
if ((int)newString[i] >128)
{
TRACE(" JUNK Characters in Application Error message FROM DCE IS = "<<(char)newString[i]<<"++++++"<<(int)newString[i]);
}
}
}
Can someone please show me the better approaches to find junk characters in a string..
Many Thanks
Your char probably is represented signed. Cast it to unsigned char instead to avoid that it becomes a negative integer when casting to int:
if ((unsigned char)newString[i] >128)
Depending on your needs, isprint might do a better job, checking for a printable character, including space:
if (!isprint((unsigned char)newString[i]))
...
Note that you have to cast to unsigned char: input for isprint requires values between 0 and UCHAR_MAX as character values.