Communication problem with C++

Hi!

My name is Elisa and I am newbie with Arduino. I connect with Arduino from C++, sending commands to Arduino trhough the COM port. Commands are formated as a String.
Each command string means a LED to be lighted on or a Servo to turn on.

When I just turn on a led or activate a servo everything is ok.
Here is how I send the command to Arduino from C++

Serial *serialPort1;
serialPort1 = new Serial("COM4");
. . .
//'buffer' has the information with the terminal of the arduino where the led/servo is and the voltage
//to apply to the led/servo
buffer = "05100";
if (serialPort1->WriteData(buffer, sizeof(buffer)) == false)
std::cout << "ERROR sending data\n";

But when I do everything at the same time (first I turn on a led,a wait a second (Sleep(1000)) and I activate the servo), this did not work.

To make it work I have to send the order twice so it works. If I send the order just once then it doesn't work. This makes no sense to me.
This is the code that sends two commands (to led and servo)

//led
buffer = "05100";
if (serialPort1->WriteData(buffer, sizeof(buffer)) == false)
std::cout << "ERROR sending data\n";
if (serialPort1->WriteData(buffer, sizeof(buffer)) == false)
std::cout << "ERROR sending data\n";

Sleep(1000);

//servo
buffer = "08100";
if (serialPort1->WriteData(buffer, sizeof(buffer)) == false)
std::cout << "ERROR sending data\n";
if (serialPort1->WriteData(buffer, sizeof(buffer)) == false)
std::cout << "ERROR sending data\n";

Sleep(1000);

And this is the code of the Arduino program that is listening to the COM for commandas to LED and Motor.

#include <Servo.h>

int terminal1, terminal2, tension1, tension2, tension3, pos1, pos2, pos3, max_ang;
float pos_f;
char c;
char *envio;
Servo g_servo8, g_servo9, g_servo10, g_servo11, g_servo12, g_servo13;

void setup(){
//crea el objeto serial
Serial.begin(9600);
max_ang = 180;

//leds
pinMode(5, OUTPUT);
//servos
pinMode(8, OUTPUT);
g_servo8.attach(8);
}

void loop(){

//el arduino espera a recibir algo
while (Serial.available() > 1){

//lee el terminal
terminal1 = Serial.read();
terminal1 = (terminal1 - 48)*10;
terminal2 = Serial.read();
terminal2 = terminal2 - 48 + terminal1;

delay(5); //espera para que le lleguen todos los datos antes de leerlos

if ( terminal2 == 5){
//LEDS
//lee la tension
tension1 = Serial.read();
tension1 = (tension1 - 48)*100;
tension2 = Serial.read();
tension2 = (tension2 - 48)10 + tension1;
tension3 = Serial.read();
tension3 = 2
(tension3 - 48 + tension2);

analogWrite(terminal2, tension3);

}
else{
//servos
pos1 = Serial.read();
pos1 = (pos1 - 48)*100;
pos2 = Serial.read();
pos2 = (pos2 - 48)*10 + pos1;
pos3 = Serial.read();
pos3 = (pos3 - 48) + pos2;
pos_f = (float)pos3/100.0 * max_ang;

g_servo8.write(pos_f);
}
}//end while
}

Is that normal? Why does this happen?

Thank you!

Elis:
Common error with a small difference. You check for serial to have 2 characters available (instead of the usual 1 character that available() > 0 ensures) and then you read more than 2 times.

Arduino is very much faster than serial data arrives. Perhaps > 1 should be >= characters to be read?

  while (Serial.available() > 1){

//lee el terminal
    terminal1 = Serial.read();
    terminal1 = (terminal1 - 48)*10;
    terminal2 = Serial.read();
    terminal2 = terminal2 - 48 + terminal1;

delay(5); //espera para que le lleguen todos los datos antes de leerlos
   
    if ( terminal2 == 5){
      //LEDS     
      //lee la tension
      tension1 = Serial.read();
      tension1 = (tension1 - 48)*100;
      tension2 = Serial.read();
      tension2 = (tension2 - 48)10 + tension1;
      tension3 = Serial.read();
      tension3 = 2
(tension3 - 48 + tension2);

analogWrite(terminal2, tension3);

}
    else{
      //servos
      pos1 = Serial.read();
      pos1 = (pos1 - 48)*100;
      pos2 = Serial.read();
      pos2 = (pos2 - 48)*10 + pos1;
      pos3 = Serial.read();
      pos3 = (pos3 - 48) + pos2;
      pos_f = (float)pos3/100.0 * max_ang;

g_servo8.write(pos_f);
   }
  }//end while
}

Commands are formated as a String.

    buffer = "05100";
    if (serialPort1->WriteData(buffer, sizeof(buffer)) == false)

That's not a String. It's a string. There is a world of difference in that one little (or big) letter.

    . . .

I'm pretty sure that this won't compile, and IS critical for us to know to help determine your problem.

But when I do everything at the same time (first I turn on a led,a wait a second (Sleep(1000)) and I activate the servo), this did not work.

There is so much wrong with this statement. First, you can't do any two things at the same time, let alone everything.

Second, you can't turn on an LED on the PC. Even if you could, you didn't show the code for doing that.

Third, sleeping means that you aren't doing diddly for a long time. That hardly fits with the idea of doing "everything at once".

Finally, you can't attach a servo to the PC, let alone activate it.

To make it work I have to send the order twice so it works. If I send the order just once then it doesn't work. This makes no sense to me.

Perhaps you are not aware that opening the serial port resets the Arduino. It is not obvious what is happening in the ... part of your code. So, it isn't obvious what the code is doing. So, it should be obvious that we can't tell you exactly what is wrong.

g_servo8.attach(8);

You attached the servo to the smiley face on your Arduino? Which model is it? Mine doesn't have a smiley face pin.

Plus, of course everything GoForSmoke says is quite right.

Hi!
Thanks for your quick answer!
I've tried your suggestion (Serial.available() >= 5) but it doesn't work, in fact, Arduino stays waiting forever. I checked the code in
the monitor serial and it works, the problem appears when I do it from C++.

I also tried making a String in the Arduino code until I read a character which I use as an end, but it doesn't work from C++. Here is
this new code:

int orden[5];
[. . .]
i = 0;
continue = 1;
while (continue == 1){
while (Serial.available() > 0){
n = Serial.read();
if (n!='/')
orden = n;

  • else*

  • continue = 0;*

  • i++;*

  • }*

  • }*
    _ terminal1 = (orden[0] - 48)*10;_

  • terminal2 = orden[1] - 48 + terminal1;*

  • delay(5); //espera para que le lleguen todos los datos antes de leerlos*

  • [... the rest is nearly the same as before]*
    sorry! any new idea about what is happening?

There is a reason why we ask people to post ALL of there code. There is a reason why we ask people to post code using the # icon. Look at your code. Look at the code you posted. Are they the same? Of course not. But, you'd like us to guess what the forum did to your improperly posted code.

Here is the C++ code:

#include "stdafx.h"
#include <iostream>
#include "Serial.h"

int _tmain(int argc, _TCHAR* argv[])
{

	LPCWSTR portName = L"COM4";
	Serial *serialPort1;
	serialPort1 = new Serial(portName);
	int a = 0;
	int b = 0;
	int c, i, continuar;
	char *buffer;


	while(b < 10){

		if (a == 0){
			if ((0 <= b) && (b < 5)){
				buffer = "05100";
			}
			else if ((5 <= b) && (b < 9)){
				buffer = "05050";
			}
			else{//b==9
				buffer = "05000";
			}
			a = 1;
		}
		else{
			if ((0 <= b) && (b < 5)){
				buffer = "06100";
			}
			else if ((5 <= b) && (b < 9)){
				buffer = "06050";
			}
			else{//b==9
				buffer = "06000";
			}
			a = 0;
		}

		if (serialPort1->WriteData(buffer, sizeof(buffer)) == false)
			std::cout << "ERROR sending data\n";
		if (serialPort1->WriteData(buffer, sizeof(buffer)) == false)
			std::cout << "ERROR sending data\n";

		Sleep(1000);

		c = b%2;
		if (c == 1){
			buffer = "08100";
		}
		else{
			buffer = "08000";
		}
		if (serialPort1->WriteData(buffer, sizeof(buffer)) == false)
			std::cout << "ERROR sending data\n";
		if (serialPort1->WriteData(buffer, sizeof(buffer)) == false)
			std::cout << "ERROR sending data\n";

		
		Sleep(1000);
		b++;
	}
}

And here is the Arduino code:

#include <Servo.h>

int terminal1, terminal2, tension1, tension2, tension3, pos1, pos2, pos3, max_ang;
float pos_f;
char c;
Servo g_servo8;


void setup(){
  //crea el objeto serial
  Serial.begin(9600);
  max_ang = 180;
 
  //leds
  pinMode(5, OUTPUT);
  //servos
  pinMode(8, OUTPUT);
  g_servo8.attach(8);
}

void loop(){
 
  //el arduino espera a recibir algo
  while (Serial.available() > 1){

    //lee el terminal
    terminal1 = Serial.read();
    terminal1 = (terminal1 - 48)*10;
    terminal2 = Serial.read();
    terminal2 = terminal2 - 48 + terminal1;

   
    delay(5); //espera para que le lleguen todos los datos antes de leerlos
   
    if ( terminal2 == 5){
      //LEDS     
      //lee la tension
      tension1 = Serial.read();
      tension1 = (tension1 - 48)*100;
      tension2 = Serial.read();
      tension2 = (tension2 - 48)*10 + tension1;
      tension3 = Serial.read();
      tension3 = 2*(tension3 - 48 + tension2);

     
      analogWrite(terminal2, tension3);

    }
    else{
      //servos
      pos1 = Serial.read();
      pos1 = (pos1 - 48)*100;
      pos2 = Serial.read();
      pos2 = (pos2 - 48)*10 + pos1;
      pos3 = Serial.read();
      pos3 = (pos3 - 48) + pos2;
      pos_f = (float)pos3/100.0 * max_ang;

      g_servo8.write(pos_f);
   }
  }//end while
}

Thanks for your help!

Thank you for posting all your code.

It is necessary to sleep a short while after opening the serial port, because the Arduino is busy resetting and waiting through the bootloader timeout. If you don't sleep about 1000 ms before sending the first command, it is usually simply lost, because your arduino program isn't running yet. So the arduino will wait forever for input that has already gone by. Which I believe is the symptom you have.

It doesn't look to me like this code is waiting before the first serial write.

-br

The Arduino is capable of writing to the serial port. The C++ code is capable of reading from the serial port. Might I suggest that you make use of these two capabilities, to see what the Arduino actually got?

You are still testing for 2 bytes and then reading 5 of them. Fail!

Perhaps in setup() you get both ends (PC and Arduino) coordinated, like modems handshaking only less complicated?

Definitely try a simpler test and proof, without extra steps --- make Arduino to receive and echo what you send from Serial Monitor or another terminal program back to the Monitor/terminal. Be sure of what is happening, flash the led on pin 13 maybe to tell the code has reached a certain point. Once you have that sureness/understanding you will be better able to plan your PC code.

A very good move is to stop using C++ String objects on Arduino. Switch to C strings which are more direct and memory efficient. Arduino has 2048 bytes of RAM for everything including the stack. A C string is a char (signed 8-bit) array with a NULL byte to signal the end of the string. Yes, you have to keep from writing past the end of the array yourself which is not so hard.

Arduino uses these libraries:
http://www.nongnu.org/avr-libc/user-manual/modules.html

This is string.h with the C string and memory manipulation functions:
http://www.nongnu.org/avr-libc/user-manual/group__avr__string.html

I finally made a combination of all your suggestions and it's working. Thank you very much to everyone!
Cheers!