I am trying to print an integer alongside a string but it's not really working out and am getting confused.
int cmdSeries = 3;
Serial.println("Series : " + cmdSeries);// That's where the problem occur
In visual basic we used to do it this way:
Dim cmdSeries As Integer
Console.Writeline(""Series : {0}", cmdSeries)
So i've tried it with Serial.println but it returns this error :
call of overloaded 'println(const char [14], int&)' is ambiguous
Can anyone help my out, I want to achieve this without using any libraries and in a clean way.
There is a huge difference between Arduino String class and regular C-string.
The first one overloads addition operator, but there is almost excessive usage of dynamic memory. Mainly if you use something like:
String sth = String("blabla") + intVar + "something else" + floatVar;
Much better is just using:
Serial.print("Series : ");
Serial.println(cmdSeries);
Btw, this string literal resides in Flash and RAM memory, so if you want to force using flash only:
Serial.print(F("Series : "));
But it's for AVR based Arduinos only. This macro can save a lots of RAM, if you are using lots of literals.
EDIT:
Sometimes I use this:
template <class T> inline Print & operator<<(Print & p, const T & val) {
p.print(val);
return p;
}
// ...
Serial << F("Text ") << intVar << F("...") << "\n";
It prints each part separately, no concatenations or so.
Try this
int cmdSeries = 3;
Serial.println(String("Series : ") + cmdSeries);
Related
I am trying to create a software lighting desk by using Qt and Arduino with a DMX Shield. I've been able to establish communication between these two and can send commands over to Arduino Mega (at the moment the communication goes only one way). I am periodically (every 200 ms) sending values of 11 faders to Mega as a String.
eg.: A123 B234 C050 ... J222 M255
The values in the string above are variables based on the position of the sliders and should be used to adjust the values of light intensities saved into each fader on the Mega side. The Letters in each section identify corresponding fader. A = fader1, B = fader2, ... Just for clarity: I can bring up a light/s at a specific intensity -> these intensities are then assigned to a fader and when that fader is moved I want these values to adjust and be sent out to the actual lights/dimmers. The calculations work fine but my Mega would eventually become unresponsive.
I think my problem is parsing the incoming string. I have tried the strtok() method and readStringUntil() to no avail. It is also difficult to monitor the incoming strings in Serial Monitor as this is used for the communication with Qt.
Would be happy for any kind of help. Please ask questions if anything is unclear.
Edit:
This is one of my attempts at solutions
const char delim[2] = " ";
char *token;
if(Serial.available())
{
//incomingMessage = Serial.readString();
incomingMessage = Serial.readStringUntil("\n"); // read the whole string until newline
//Serial.println(incomingMessage);
const char* str = incomingMessage.c_str(); // convert it to a C String terminated by a null character "\0"
//Serial.println(str);
token = strtok(str, delim); // first part is a first section until delimiter occurs "-space- "
//Serial.println(token);
LX_Rated.commandLineResolve(token); // resolve it
while( token != NULL ) { // continue splitting and resolving the incoming message until it reaches the end
token = strtok(NULL, delim);
LX_Rated.commandLineResolve(token);
}
}
Edit2:
I have confirmed that I receive the whole string sent by Qt. When I try to tokenise it using the strtok() function and print out the first token I get back the whole string, the other tokens are empty. I don't see any mistake in my code here. I even tried to slow down the sending of the string from Qt to one per 5 sec. Does anybody have any idea what is going on? I don't see why this standard function doesn't work as expected. Please see the amended code below.
if(Serial.available()) {
incomingMessage = Serial.readStringUntil("\n");
Serial.println("ok");
Serial.flush();
char* nullTerminatedIncomingMessage = incomingMessage.c_str();
const char delimiter = " ";
char* token;
char* token1;
char* token2;
//char* secondToken;
token = strtok(nullTerminatedIncomingMessage, delimiter);
token1 = strtok(NULL, delimiter);
token2 = strtok(NULL, delimiter);
Serial.println(token); // print the first section
//Serial.println(incomingMessage);
Serial.flush();
Serial.println(token1);
Serial.flush();
Serial.println(token2);
Serial.flush();
//while(token != NULL)
// secondToken = strtok(NULL, delimiter);
//Serial.println(secondToken);
//Serial.flush();
incomingMessage = "";
}
Your mistake - at the very least - is in assuming that all the input is available when you expect it. You need to defer processing until an entire line has been assembled. Serial.readStringUntil blocks until an entire line is available, and that's not what you expect. You essentially need to replace Serial.available() with Serial.lineAvailable(), except the latter is not implemented.
This answer contains a complete solution to your issue - including both Qt and Arduino code - and an Arudino emulation layer. It might be a good starting point, especially that you can easily co-debug both Qt and Arduino projects from within one application and using one debugger!
As for difficulty in monitoring communication, you can(in Qt) dump everything you read into console and do the same for everything you write into the serial port. It will show in the console tab of QtCreator
#include <QDebug>
...
qDebug() << "whatever" << endl;
Aso for parsing the data you read from to serial port, take a look at this to see how to easily split the sliders info into individual strings(with QRegExp)
How Can I Split a String According To Delimiters in Qt?
I can't possibly guess why your arduino would be unresponsive without the code.
EDIT:
Is it possible, when you generate the string in Qt, that you separate the tokens by something other than space? Maybe tab("\t") or something? strtok accepts multiple delimiters in the delimiter string, may be something to try.
If that is not the case, there is the unlikely possibility that something's wrong with the strtok(...) function(btw. it modifies the original string, that in itself could be a problem). Also, strtok could return a NULL pointer, you don't seem to handle that case(some wrong input - print a message). You could try this as an alternative to normal strtok:
/**
* #brief custom strtok replacement with the same interface
* It does not modify the original string
* Token length is limited to 63 characters
* #param ptr pointer to the string or NULL
* #param delim delimiting character(only the first character will be used)
*/
const char * my_strtok(const char * ptr, const char * delim) {
// Persistent variables, it will remember pointer to the processed string
static const char * src;
static char buffer[64]; // Token is limited to 63 characters
if(ptr) { // Remember the pointer, if a new one was supplied
src = ptr;
}
if(src == NULL || *src == '\0')// Invalid / empty string / no next token - return NULL
return NULL;
char i = 0;
for(i = 0; i < 63 && *src != delim[0]; i++) {// Copy token until delimiter or end of buffer
buffer[i] = *(src++);
}
if(*src == delim[0]) // Skip over the delimiter to the begining of the next token
++src;
buffer[i] = '\0'; // Any returned string must be terminated
return buffer;
}
#include <cstdlib>
#include <cstring>
#include <cassert>
void test() {
const char * str1 = "123 456 asdf jkl;";
assert(strcmp("123", my_strtok(str1, " ")) == 0);
assert(strcmp("456", my_strtok(NULL, " ")) == 0);
assert(strcmp("asdf", my_strtok(NULL, " ")) == 0);
assert(strcmp("jkl;", my_strtok(NULL, " ")) == 0);
assert(NULL == my_strtok(NULL, " "));
assert(NULL == my_strtok(NULL, " "));
assert(strcmp("123", my_strtok(str1, " ")) == 0);
}
How can i find a specific character in a QFile which has a text in it?
for example i have ' $5000 ' written somewhere in my file. in want to find the "$" sign so i will realize that I've reached the number.
I tried using QString QTextStream::read(qint64 maxlen) by putting 1 as the maxlen :
QFile myfile("myfile.txt");
myfile.open(QIODevice::ReadWrite | QIODevice::Text);
QTextStream myfile_stream(&myfile);
while(! myfile_stream.atEnd())
{
if( myfile_stream.read(1) == '$')
{
qDebug()<<"found";
break;
}
}
and i get "error: invalid conversion from 'char' to 'const char* "
i also tried using the operator[] but apparently it can't be used for files.
Read in a line at a time and search the text that you've read in
QTextStream stream(&myFile);
QString line;
do
{
line = stream.readLine();
if(line.contains("$"))
{
qDebug()<<"found";
break;
}
} while (!line.isNull());
The error message you've posted doesn't match the issue in your code. Possibly the error was caused by something else.
QTextStream::read returns QString. You can't compare QString and const char* directly, but operator[] can help:
QString s = stream.read(1);
if (s.count() == 1) {
if (s[0] == '$') {
//...
}
}
However reading a file by too small pieces will be very slow. If your file is small enough, you can read it all at once:
QString s = stream.readAll();
int index = s.indexOf('$');
If your file is large, it's better to read file by small chunks (1024 bytes for example) and calculate the index of found character using indexOf result and count of already read chunks.
a single char could be read with
QTextStream myfile_stream(&myfile);
QChar c;
while (!myfile_stream.atEnd())
myfile_stream >> c;
if (c == '$') {
...
}
myfile_stream.read(1) - this is not good practice, you should not read from file one byte at a time. Either read the entire file, or buffered/line by line if there is a risk for the file to be too big to fit in memory.
The error you get is because you compare a QString for equality with a character literal - needless to say that is not going to work as expected. A string is a string even if there is only one character in it. As advised - use either the [] operator or better off for reading - QString::at() const which is guaranteed to create no extra copy. You don't use it on the QFile, nor on the QTextStream, but on the QString that is returned from the read() method of the text stream targeted at the file.
Once you have the text in memory, you can either use the regular QString methods like indexOf() to search for the index of a contained character.
in want to find the "$" sign so i will realize that I've reached the
number.
It sounds to me that you're searching for the '$' symbol because you're more interested in the dollar value that follows it. In this case, I suggest reading the files line by line and running them through a QRegExp to extract any values you're looking for.
QRegExp dollarFind("\\$(\\d+)");
while(!myfile_stream.atEnd()){
QString line = myfile_stream.readLine();
if (dollarFind.exactMatch(line)){
QStringList dollars = dollarFind.capturedTexts();
qDebug() << "Dollar values found: " << dollars.join(", ");
}
}
I apologize if this is a stupid question (It probably is) but I am having a hard time getting a function to work correctly.
My code as it stands:
#define photoPin A0
char photoCode[] = "L";
void loop(void) {
analogSensor(photoPin, photoCode);
delay(5000);
}
void analogSensor(int sensorPin, char* sensorCode) {
//Poll the Photo Cell and append that to the buffer
int sensorValue=analogRead(sensorPin);
Serial.print(sensorCode);
sprintf(buf + strlen(buf), "," + sensorCode + ":%04i", sensorValue);
}
When I try to compile this, I get the following message:
In function 'void analogSensor(int, char*)':
i2c_Sensor:104: error: invalid operands of types 'const char [2]' and 'char*' to binary 'operator+'
But, if I comment out the sprintf line, it compiles fine, and ever 5 seconds, an "L" prints out on the screen. Ultimately, I am confused as all get out, and don't know where to turn at this point.
Any help is appreciated.
The last one the formatting got borked :)
I'm afriad you cant concatenate char* with the + operator :) You'd have to call sprintf or strcat :) See your local man pages.
Instead of this:
sprintf(buf + strlen(buf), "," + sensorCode + ":%04i", sensorValue);
Try this:
sprintf( buf+strlen(buf), ",%s:%04i", sensorCode, sensorValue );
I have:
Arduino MEGA 2560;
Ethernet+SD shield http://www.amazon.com/dp/B0022TWQ22/?tag=stackoverfl08-20 ;
SD card 2GB FAT.
SD contains 400 files with names 00000000; 0000001; 0000002; ... 00000098; 0000099; 0000100; ... 00000398; 00000399.
I need to construct String var which will contain all the Filenames separated by ";" like this:
sdata = "0000001;0000002;0000003 ... 00000398;00000399;";
Code:
#include <SdFat.h>
#include <SPI.h>
const uint16_t chipSelect = SS;
char cnamefile[9];
String sdata="";
SdFat sd;
SdFile file;
void setup() {
Serial.begin(9600);
Serial.println("hi");
sdata="";
if (!sd.begin(chipSelect, SPI_HALF_SPEED)) sd.initErrorHalt();
Serial.println("List files");
while (file.openNext(sd.vwd(), O_READ)) {
file.getFilename(cnamefile);
file.close();
sdata = sdata + String(cnamefile) + ";";
}
Serial.print(sdata);
}
void loop() {
}
Listening to the COM port i see:
hi
List files
00000005;00000006;00000007;00000008;00000009;00000010;00000011;00000012;00000013;00000014;00000015;00000016;00000017;00000018;00000019;00000020;00000021;00000022;00000023;00000024;00000025;00000026;00000027;00000028;00000029;00000030;00000031;00000032;00000033;00000034;00000035;00000036;00000037;00000038;00000039;00000040;00000041;00000042;00000043;00000044;00000045;00000046;00000047;00000048;00000049;00000050;00000051;00000052;00000053;00000054;00000055;00000056;00000057;00000058;00000059;00000060;00000061;00000062;00000063;00000064;00000065;00000066;00000067;00000068;00000069;00000070;00000071;00000072;00000073;00000074;00000075;00000076;00000077;00000078;
How to fix this problem and put all filenames in one variable?
Information for: 400 names and 400 ";" its 3600 bytes. When i try to read any file and put all its contents (more than 3600 bytes) in "String sdata" it works normally. Problem only with listing.
Please help me in sorting out this issue.
This seems about the correct place that your program will fail. This innocent line is your problem:
sdata = sdata + String(cnamefile) + ";";
String concatentation like this will use 2X the memory of the sdata for a short moment. This is the how you should view the sequence of operations in that one line
// compiler has done this for you:
String temp1234 = sdata + String();
// note that at this moment, memory usage is now 2x sdata
String temp1235 = temp1234 + ";";
// now you can have 3x the memory used
// assignment to variable
sdata = temp1235;
// now can delete temporary variable
// compiler will do this
//temp1234.delete()
//temp1235.delete()
You are trying to create strings up to 3k bytes but have only 8k total RAM, so will not be able to do the above.
This demonstrates a couple of points about Strings. Your concatenation above on one line, is not necessarily better than this two line form:
sdata = sdata + String(cnamefile);
sdata = sdata + ";";
In this second form, you are ensured there will only be one temporary variable for the intermediate result.
This leads to the next hint. You should be thinking how am I going to escape the temporary variable. That is why we have += operator. Your best chance is to concatenate like this:
sdata += String(cnamefile);
sdata += ";";
If the += operator is available on the String class, the compiler will use this. That operator may be able to use a more memory efficient way of concatenation. For example, if the String was preallocated with some extra memory, then it could just place the new characters into the existing buffer.
In general this is a great learning method about strings in constrained memory spaces, because you must understand some compiler internals and operator details that are often ignored in large CPU environments.
Given the sizes you are suggesting, you will probably only be able to fit in RAM if you change to an approach of pre-constructing a String buffer and filling it with the file names. In other words: don't use String on a microcontroller.
I want to add a new line in this. This is my sample code:
ui->button->setText(" Tips " + "\n" + TipsCount );
This is the error it shows:
invalid operands of types 'const char [7]' and 'const char [2]' to binary 'operator+'
But when I add to label it gets appended!
ui->label->setText(name + "\n" + City );
Can someone please help me?
This is a very common problem in C++ (in general, not just QT).
Thanks to the magic of operator overloading, name + "\n" gets turned into a method call (couldn't say which one since you don't list the type). In other words, because one of the two things is an object with + overloaded it works.
However when you try to do "abc" + "de", it blows up. The reason is because the compiler attempts to add two arrays together. It doesn't understand that you mean concatenation, and tries to treat it as an arithmetic operation.
To correct this, wrap your string literals in the appropriate string object type (std::string or QString most likely).
Here is a little case study:
QString h = "Hello"; // works
QString w = "World"; // works too, of course
QString a = h + "World"; // works
QString b = "Hello" + w; // also works
QString c = "Hello" + "World"; // does not work
String literals in C++ (text in quotes) are not objects and don't have methods...just like numeric values aren't objects. To make a string start acting "object-like" it has to get wrapped up into an object. QString is one of those wrapping objects, as is the std::string in C++.
Yet the behavior you see in a and b show we're somehow able to add a string literal to an object. That comes from the fact that Qt has defined global operator overloads for both the case where the left operand is a QString with the right a const char*:
http://doc.qt.nokia.com/latest/qstring.html#operator-2b-24
...as well as the other case where the left is a const char* and the right is a QString:
http://doc.qt.nokia.com/latest/qstring.html#operator-2b-27
If those did not exist then you would have had to write:
QString a = h + QString("World");
QString b = QString("Hello") + w;
You could still do that if you want. In that case what you'll cause to run will be the addition overload for both operands as QString:
http://doc.qt.nokia.com/latest/qstring.html#operator-2b-24
But if even that didn't exist, you'd have to call a member function. For instance, append():
http://doc.qt.nokia.com/latest/qstring.html#append
In fact, you might notice that there's no overload for appending an integer to a string. (There's one for a char, however.) So if your TipsCount is an integer, you'll have to find some way of turning it into a QString. The static number() methods are one way.
http://doc.qt.nokia.com/latest/qstring.html#number
So you might find you need:
ui->button->setText(QString(" Tips ") + "\n" + QString::number(TipsCount));