Loose data from PC to PLC while saving EEPROM data

Good morning

I have a problem while load all the parameters into EEPROM, using a VB program.
It happens that some parameters aren't save...
My syntax is "P<0#25>"

0 is the parameter and 25 is the value that I want to save on it.

To verify the data, I download to PC all the EEPROM.
Unfortunately, not all the data are saved on EEPROM.

Look the following:

<151#25>
<152#25>
<0#0>
<154#25>
<155#25>
<156#25>
<0#0>
<158#25>

As you can check, When I send parameter 153, something happens and both parameter and value are recognized as '0'...
Also to the parameter 157 and others more.

This is the code that I'm using to recognize what I'm send from PC to PLC.
For me, looking on it, I don't find any problem... but perhaps exist...

//CARREGA PARAMETROS NA EEPPROM (ok)
if (command == 'P'){
String sTextoLido;
String sParametro;
String sValor;
int length;
while(Serial.available()){
sPar[0] = Serial.read();
if (sPar[0]==60){
sVal="<";
}
else if(sPar[0]==62)
{
sVal=">";
}
else if(sPar[0]==35)
{
sVal="#";
}
Else
{
sVal=itoa(atoi(sPar),Debug,10);
}
sTextoLido += sVal; //CONCATENA
}
int CaractereINI = sTextoLido.indexOf('<');
int CaractereDIV = sTextoLido.indexOf('#');
int CaractereFIM = sTextoLido.indexOf('>');
if (CaractereINI != -1 && CaractereDIV != -1 && CaractereFIM != -1){
sParametro= sTextoLido.substring(CaractereINI+1, CaractereDIV - CaractereINI );
sValor = sTextoLido.substring(CaractereDIV + 1, CaractereFIM );
}

char this_char[sParametro.length()+1];
sParametro.toCharArray(this_char,sizeof(this_char));
int intParametro=atoi(this_char);

char this_char1[sValor.length()+1];
sValor.toCharArray(this_char1,sizeof(this_char1));
int intValor=atoi(this_char1);

EEPROM.write(intParametro,intValor);

Serial.Print ("<");
Serial.Print (intParametro);
Serial.Print ("#");
Serial.Print (intValor);
Serial.println(">");
delay(25);
command=0;
}

Please let me know if you have any suggestion.

Thanks on advance
Best regards
Pedro Ferrer

if (sPar[0]==35)

I know I keep banging on about this, but it is pretty important:

if (sPar[0]=='#')
}
        Else
        {

?!

You don't say what the serial line speed is but a 25 millisecond delay in addition to the EEPROM write time won't help the situation if the line is running at high speed - it increases the chance of buffer overflow.

How is sPar defined? You only ever overwrite the first element in the array:

        sPar[0] = Serial.read();

Unless you are storing a NULL in sPar[1] somewhere else, this won't work:

            sVal=itoa(atoi(sPar),Debug,10);

The atoi function expects a NULL terminated array. If sPar[1] is NULL, then the atoi function's operation will be undone by the itoa function, so you will have simply wasted a lot of resources copying sPar[0] to sVal[0].

        if (sPar[0]==60){
        else if(sPar[0]==62)
        else if(sPar[0]==35)

What do 60, 62, and 35 correspond to?

        if (sPar[0]=='<'){
        else if(sPar[0]=='>')
        else if(sPar[0]=='#')

Is a lot easier to understand (and change).

Your code is relying on serial data actually being sent and received. You have no contingency plan for a character NOT being transmitted.

Good afternoon

Thanks for your replies.

sPar variable is defined as:

char * sPar;

and Debug as :

char Debug[40];

So Paul, what do you suggest for that?

Your code is relying on serial data actually being sent and received. You have no contingency plan for a character NOT being transmitted.

I've tried to return to PC the "" syntax.
By this way I only send info to PLC from PC when I receive on serial.
But still on same... have "<0#0>"...

Please let me know
Thanks on advance
Best regards
Pedro Ferrer

sPar variable is defined as

You are just asking for trouble.

You have defined a pointer, but not made it point to anything. Then, you are using it as though there is place to put data.

There is no reason that I can see for sPar to be more than a scalar variable. Change sPar's declaration to:

char sPar;

Then, change all the sPar[0] occurrences to sPar.

I've tried to return to PC the "" syntax.

When? If the PC sends P<153#25> but the P is lost, what do you do? What if the Arduino receives "P<53#25>", instead? Or "P<15325>"? Or "P<153#5>"?

Serial data is not guaranteed to be delivered. You need to plan for each part of the data to be incorrectly delivered. If, instead of "P<153#25>", you sent "P3:153#2:25", then a packet missing the "<" or "> would be easily recognized as corrupt (the data stream might look like "P3:153#2:25P3:153#2:25>" (data after the > before another < is a corrupt packet). If the packet does not start with a recognizable letter, the packet is corrupt. If the packet does not contain a "#", it is corrupt. If the number of characters after the colon does not match the value before the colon, the packet is corrupt.

This is a bit more difficult to implement, but corrupt packets can be detected, and the Arduino can fail to acknowledge them, which should make the PC resend them.

Hello PaulS

Thanks once again by your help.

I'm sending the follow kind of package to PLC... "P<100#25>" then wait for an answer from PLC...""
The '' message is received just after the info on EEPROM.
So, now I can send "P<101#25>" and so on.

I'm testing the syntax... I'm checking '<', '>' and '#' chars...

The 'P' is received ...

if (command == 'P'){

Otherwise, don't enter on condition..

I still don't get why have '<0#0>' as result... but it means and it seems that I've received all, because I have 'P' (because is entering on condition) and '<','>' and '#' because the symbols are returned back to PC. ('<0#0'>)...

Thanks once again
Best regards
Pedro Ferrer

I'll ask again. If you send P<153#25>, and the '1', '5', or '3' is lost, what will the Arduino do? It will determine that the address is either 53, 13, or 15, instead of 153. It will then write the data in the wrong place. Then, when you try to read the data from 153, it will return bogus data, because nothing is stored there.

Look at what happens in your code if the <, > or # is what is lost. The value in CaractereINI, CaractereDIV, or CaractereFIM will be -1. When that happens, nothing is stored in sParametro or sValor, but you happily convert the data there to integers, anyway. The results, of course, will be 0.

Hello PaulS

Clear for me now. Thanks by your explanation.
I have an idea to turn around to the loss data problem.

If info that returned back to PC is different from the one that was sent to PLC..
eg:
PC->PLC "P<100#25>"
If PLC->PC is equal to <100#25> that I can send parameter 101, otherwise, send again parameter 100...

What do you think?

For me is strange, because I have a routine to send all EEPROM data from PLC to PC with a delay(25) and I don't have any loose data...

Please let me know
Thanks on advance
Best regards
Pedro Ferrer

If info that returned back to PC is different from the one that was sent to PLC..
eg:
PC->PLC "P<100#25>"
If PLC->PC is equal to <100#25> that I can send parameter 101, otherwise, send again parameter 100...

What do you think?

That should work. The chances of losing data are pretty small, so sending the same data twice should be an infrequent occurrence. Sending the same data a third time (or more) is possible, but unlikely.

Good night

PaulS:

            sVal=itoa(atoi(sPar),Debug,10);

The atoi function expects a NULL terminated array. If sPar[1] is NULL, then the atoi function's operation will be undone by the itoa function, so you will have simply wasted a lot of resources copying sPar[0] to sVal[0].

So, I've changed to...
char sPar; instead char * sPar;

as you suggest. But now I need to convert to Integer...
sVal=atoi(sPar);

But have an error...

1>c:\arduino\arduinoIDE\sketches\Codino1_vsAddIn/..\Codino1.pde:3360: error: initializing argument 1 of 'int atoi(const char*)'
1>c:\arduino\arduinoIDE\sketches\Codino1_vsAddIn/..\Codino1.pde:3360: error: invalid conversion from 'int' to 'char*'

What I'll have to change to correct it?

I'll appreciate your prompt help once again
Thanks on advance
Best regards
Pedro Ferrer

If sPar contains an ASCII decimal digit, simply subtract the value of the ASCII zero character '0'.

Hello

Thanks AWOL

digit '0' is 48 on DEC
digit '2' is 50 on DEC...

so 50-48 will give me digit '2'!
done!

I'll try later at night.

Thank you
Best regards
Pedro Ferrer

so 50-48 will give me digit '2'!

Being pedantic, no.

50 - 48 = 2.

Or, more clearly:
'2' - '0' = 2