I am learning mbed, and doing some examples. My code is to send a random string "ccc" from my pc to microcontroller LPCXpresso.
enter code here
#include "mbed.h"
DigitalOut myled(LED1);
Serial pc(USBTX, USBRX);
int main() {
char c;
char buffer[128];
myled = 1;
pc.gets(buffer, 4);
pc.printf("I got '%s'\n", buffer);
if(buffer == 'ccc'){
myled = 0;
}
}
I enter 'ccc', and the printf does return the message: I got 'ccc'. However, in the if statement, if I use (buffer == 'ccc'), I see the error message: Error: Operand types are incompatible ("char *" and "int") in "main.cpp". If i use (buffer == "ccc") my led does not light up as expected since I know for sure the buffer is ccc.
How could I make it works?
You cannot compare strings like that in C/C++. Use strcmp. E.g.:
if (strcmp(buffer, "ccc") == 0) {
Related
Hello friends of the community. I spend a lot of time trying to solve this issue and I hope you can help me.
I'm ussing the library from this link https://github.com/oxullo/Arduino-MAX30100 in order to implement my project. The arduino code executes quite well, but when I try to receive data from the serial port, who's connected to an HC-05, I can't concatenate the data when pox.update() is present in the loop, the data received is like:
R
o
b
e
r
t
o
A
n
d
r
e
s
So I need to cancatenate it to shows it in a 128x64 oled display. Moreover, the if (incomingByte == 'T') condition seems not to be executed, as it the oled display doesn't show the getStringfromProgMem(3) char. The loop code is:
void loop() {
if (Serial.available() > 0) {
incomingByte = Serial.read();
if (incomingByte == 'T') {
palabra = getStringfromProgMem(3);
c = 0;
} else {
palabra.concat(incomingByte);
}
}
pox.update();
display.clearDisplay();
estado = digitalRead(STATE);
estado ? (enlace()) : (noenlace());
unsigned long tiempoActual = millis();
if (tiempoActual - tiempoAnterior >= intervaloEvento) {
rate = pox.getHeartRate();
spo = pox.getSpO2();
if (rate && palabra != getStringfromProgMem(3)) {
c++;
}
if (c == 60) {
c = 0;
}
/*Serial.print(rate);
Serial.print(',');
Serial.print(spo);
Serial.print(',');
Serial.println(c);*/
tiempoAnterior = tiempoActual;
}
mostrar(rate, 15, 35);
mostrar(spo, 105, 35);
mostrar(getStringfromProgMem(0), 10, 52);
mostrar(getStringfromProgMem(1), 100, 52);
/*outputValue = (VERF * analogRead(ANALOG)) / 1024;
smoothedVal = smoothedVal + ((outputValue - smoothedVal) / SAMPLES);
comparacion(smoothedVal);*/
//
display.display();
}
The code shows just the first letter in the oled display and ignores the others. I'm using this libraries also:
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include "MAX30100_PulseOximeter.h"
#include <avr/pgmspace.h>
And I declarate the variables "incomingByte" and "palabra" as globals:
char incomingByte;
String palabra="";
The code palabra.concat(incomingByte) executes well without the "pox.update()" method. What I'm doing wrong?
I think that I solved it. The issue was generated due a memory leak of my Arduino. When I tried to concatenate the String "palabra", the Arduino simply didn't do it because of a memory leak. If any of you have troubles handling the Strings and the Arduino simply doesn't concatenate your strings, I suggest visit this site:
https://www.best-microcontroller-projects.com/arduino-string.html
Now I can't realice how to handle the c-strings but is question of time.
Any of you have an idea how to clean the static char palabra[15], *pSdata = palabra;?
When I use strings is simply to write palabra="";. But now, I have no idea how to do it. I hope you can help me.
Greetings.
I'm using an android app to send values to control servos.
Code:
char inputData[4];
char buffer[3];
void loop()
{
if(Serial.available() > 3) {
for (int i = 0; i < 4; i++){
inputData[i] = Serial.read();
}
char buffer[4];
buffer[0] = inputData[1];
buffer[1] = inputData[2];
buffer[2] = inputData[3];
buffer[3] = '\0';
int angle = atoi(buffer);
Serial.write(angle);
}
}
Issue: I'm getting the values + A-F letters to address each servo - A10, A180, B30 etc. Now the trouble is turning this to an actual integer. As you can see I've declared a character array to store the integers in and as suggested in a post on the arduino forum, I added a \0 at the end of the array. Currently, the Atoi returns random characters, mostly squares and some random numbers. I've tried even assigning them to a string and then .toInt() but same issue there, mostly squares.
Any ideas?
Thanks!
Use print or println to see the number as text. write sends it as byte and Serial Monitor shows a symbol with that ASCII code.
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);
}
I'm just learning how to handle sockets and TCP connections in C. I've got an application (a long one) which basically sends and receives char arrays with the system call write from server to client and vice versa (two separate C applications of course). As long as I use it with a local connection, on the same PC, running the server on a terminal and the client on an another, everything just works fine and the data arrives at the destination. But if I try it with the server on one computer and the client on another but on the same internet line, passing to the client an address like 192.168.1.X (took from the machine on which the server is running), after the connection is established, I've got an error that tells me that the number of expected bytes (which I pass before sending the real char[]) isn't arrived. Same thing if I try the server on my PC, and the client on another one with a different line on a different provider.
There's something I'm missing, are there any limitations in sending a bunch of bytes in sequence?
The code where the error pops up.
SERVER SIDE:
r=htonl(lghstr);
w=write(myFd,&r,sizeof(int));//writes the number of incoming bytes
if(w<0) perror("writeServer4"),exit(-1);
w=write(myFd,tmp->string,lghstr);
if(w<0) perror("writeServer5"),exit(-1);
if(w!=lghstr) perror("ERROR");
CLIENT SIDE
rC=read(fdc,&cod,sizeof(int));//read incoming number of bytes
lghstr=ntohl(cod);
if(rC<0) perror("readClient3"),exit(-1);
rC=read(fdc,dest,lghstr);
if(rC<0) perror("readClient4"),exit(-1);
if(rC!=lghstr) perror("error : "), printf("didn't read the right number of bytes"),exit(-1);
Now this is basically repeated a lot of times, let's even say 300 times, and it's with big numbers that the program doesn't work.
This is the problem:
rC=read(fdc,dest,lghstr);
...
if(rC!=lghstr) perror("error : ")
The #1 fallacy with socket programming is expecting that recv() and read() will return exactly the same number of bytes corresponding to the write/send call made by the other side.
In reality, partial data is extremely likely and expected. The simple workaround is to loop on read/recv until you get the exact number of bytes expected:
size_t count = 0;
while (count < lghstr)
{
ssize_t readresult = read(fdc, dest+count, lghstr-count);
if (readresult == -1)
{
// socket error - handle appropriately (typically, just close the connection)
}
else if (readresult == 0)
{
// The other side closed the connection - handle appropriately (close the connection)
}
else
{
count += readresult;
}
}
The other alternative to looping is to the use the MSG_WAITALL flag with the socket. This means, using recv() instead of read(). You'll still need to handle the error cases.
rc = recv(fdc, dest, lghstr, MSG_WAITALL);
if (rc == -1)
{
// socket error
}
else if (rc == 0)
{
// socket closed by remote
}
else if (rc < lghstr)
{
// the other side likely closed the connection and this is residual data (next recv will return 0)
}
You do ntohl() on one side and not the other. That might be interpreting the bytes with the wrong value.
You should printf() the bytes on both sides and see what the int is being evaluated to.
Edit: I'm convinced this is a programming bug for the record.
If I had to guess, I'd say that you are not synchronous with the other side for some reason. You say this runs 'about 300 times'.
Try adding a magic integer to the protocol.
Heres an example of a client that sends in this order.
A magic integer which is always constant.
A lengh of bytes about to be sent.
The bytes to be sent.
This uses scatter gather mechanics (its nicer for serialization) but other than that it effectively is doing the same thing yours is doing, as a client, just adding a magic value.
When the receiver receives the data, it can validate that the data is coming in the right order, by checking what the magic number was that came in. If the magic is wrong it means the client or server has lost themselves positionally in the stream.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <err.h>
#include <time.h>
#define MAGIC 0xDEADBEEFLU
#define GARBAGE_MAX 65536
const int iterations = 3000;
char * create_garbage_buf(
void)
{
int rc = -1;
int fd = -1;
char *buf = NULL;
buf = malloc(GARBAGE_MAX);
if (!buf)
err(1, "Cannot allocate buf");
fd = open("/dev/urandom", O_RDONLY);
if (fd < 0)
err(1, "Cannot open urandom");
rc = read(fd, buf, GARBAGE_MAX);
if (rc < 0)
err(1, "Cannot read from urandom");
else if (rc != GARBAGE_MAX)
errx(1, "Expected %d bytes, but got %d reading from urandom",
GARBAGE_MAX, rc);
close(fd);
return buf;
}
int main() {
int fd, offset, i, rc;
uint32_t magic = MAGIC;
uint32_t blen = 0;
char *buf = NULL;
struct iovec vecs[3];
/* Seed poor random number generator */
srand(time(NULL));
/* Use a file for demonstration, but a socket will do just fine */
fd = open("/dev/null", O_WRONLY);
/* Create some garbage to send */
buf = create_garbage_buf();
if (fd < 0)
err(1, "Cannot open file");
/* The first vector, is always the magic */
vecs[0].iov_len = sizeof(uint32_t);
vecs[0].iov_base = &magic;
for (i=0; i < iterations; i++) {
/* The second vector represents lengh of what we send
* in this demonstration it is a number between 0 and
* GARBAGE_MAX/2.
*/
blen = rand() % (GARBAGE_MAX / 2);
vecs[1].iov_len = sizeof(uint32_t);
vecs[1].iov_base = &blen;
/* The last record is the data to send. Its another random
* number between 0 and GARBAGE_MAX which represents the offset
* in our garbage data to send */
offset = rand() % (GARBAGE_MAX / 2);
vecs[2].iov_len = blen;
vecs[2].iov_base = &buf[offset];
rc = writev(fd, vecs, 3);
if (rc < 0)
err(1, "Could not write data");
if (rc != (sizeof(uint32_t)*2 + blen))
errx(1, "Did not write proper number of bytes to handle");
printf("Wrote %u bytes from offset %u in garbage\n", blen, offset);
}
free(buf);
printf("Done!\n");
return 0;
}
Closely read the documentation for read()/write() and learn that those two functions do not necessarily read()/write() as much bytes as they were told to, but few. So looping around such calls counting until all data expected had been read/written is a good idea, not to say an essential necessity.
For examples how this could be done for writing you might like to have look at this answer: https://stackoverflow.com/a/24260280/694576 and for reading on this answer: https://stackoverflow.com/a/20149925/694576
I'm programming with arduino 1.0.5 in lunix/windows
With this piece of code:
void readSerialString () {
char buffer[8];
if(Serial.available()) {
while (Serial.available()){
sb = Serial.read();
buffer[indexB] = sb;
indexB++;
}
}
Serial.println(buffer);
}
I'm trying to send (by serial terminal) a message that can be seen in hexadecimal.
For exemple if I write: "\xaa\x22\xa1"
It will not read as hexadecimal, will it?
How can I let the program read the string in input as hexadecimal?
No your mistaking the data and it s format.
do you have access to printf ? If so use printf("%x",char) to see a char as hexadecimal.
Arduino solution
Serial.print(78, HEX) gives "4E"
see http://arduino.cc/en/Serial/Print
[edit]
I need the contrary of print. I need that the string that has been token from the serial terminal is interpreted as hex.
To do this use read(), but you will have to implement the convertion function from ascii HEX to data, as an HEX data for a byte hols on 2 chars, my function take two chars as input)
char hex_ascii_to_databyte(char c1, char c2){
char res=0;
if(c1>=48 && c1<=57) res = c1-48;
else if(c1>=65&& c1<=70) res = c1 - 65 + 0xa;
else if(c1>=97&& c1<=102) res = c1 - 97 + 0xa;
else{//error
}
//idem c2 in res2
res=res<<4;
res+=res2;
return res;
}
for each hex read, call twice read (to read the 2 ascii chars) then call this func