Jump to content
43oh

Serial not receiving all available bytes or state machine hangs


Recommended Posts

Hello All, 


 


I am attempting to use Energia (I know it's not Arduino but they are pretty much the same) to read data from a serial device that has some interesting quirks. The first issue I'm having is when using the debug code (debug = 1) the program only captures a portion of the serial data from the external device.



/*
Multple serial test

Receives from the main serial port, sends to the others.
Receives from serial port 1, sends to the main serial (Serial 0).

The circuit:
* Any serial device attached to Serial port 1
* Serial monitor open on Serial port 0:

created 30 Dec. 2008
by Tom Igoe

This example code is in the public domain.

*/

#define ACK 0x06
#define NACK 0x15
#define CSFAIL 0x51
#define debug 0
#define debugState 1
#define debugStateThree 1

byte requestData[] = {0xA5, 0x08, 0x41, 0x00, 0x3E, 0x4E, 0x20, 0x9A};
int timeSlot = 200;
unsigned long time0 = 0;
unsigned long time1 = 0;
int receiveCounter = 0;
int bytesToReceive = -1;

char reveivedData[50]; //Input array
boolean stringComplete = false; // whether the string is complete
int outputCounter = 0;
int i = 0;
int state = 0;
char inChar;

int availableBytes = 0;

void setup() {
// initialize both serial ports:
Serial.begin(115200);
Serial1.begin(115200);
// reserve 200 bytes for the inputString:
// inputString.reserve(200);

// prints title with ending line break
Serial.println("Read Data from MCP39F511");

}

void loop() {
//send read data command to MCP39F511
time1 = millis();
switch(state){
case 0:
if((time1 - time0) >= 1000){
for(i = 0; i < sizeof(requestData); i++){
Serial1.write(requestData[i]);
delayMicroseconds(timeSlot);
}
time0 = millis();
#if debugState
Serial.println("0 Send Command");
#endif
state++;
}
break;

case 1:
availableBytes = Serial1.available();
if(availableBytes > 0){
inChar = (char)Serial1.read();
if(inChar == ACK){
reveivedData[receiveCounter] = inChar;
receiveCounter++;
state++;
#if debug
Serial.print("1 Receive first byte");
Serial.print(" - inChar ");
Serial.print(inChar, HEX);
Serial.print(" - receiveCounter ");
Serial.print(receiveCounter, HEX);
Serial.print(" - state ");
Serial.print(state, DEC);
Serial.print(" - availableBytes ");
Serial.println(availableBytes, DEC);
#endif
}
else if(inChar == NACK){
//Output error message
Serial.println("Command received with success command not understood or another error in command bytes");
}
else if(inChar == CSFAIL){
//Output error message
Serial.println("Frame received with success, however, checksum did not match bytes in frame");
}
}
#if debugState
Serial.println("State #1");
#endif
break;

case 2:
availableBytes = Serial1.available();
if(availableBytes > 0){
inChar = (char)Serial1.read();
reveivedData[receiveCounter] = inChar;
bytesToReceive = inChar;
receiveCounter++;
state++;
#if debug
Serial.print("2 Receive number of bytes to receive");
Serial.print(" - inChar ");
Serial.print(inChar, HEX);
Serial.print(" - receiveCounter ");
Serial.print(receiveCounter, HEX);
Serial.print(" - bytesToReceive ");
Serial.print(bytesToReceive, DEC);
Serial.print(" - state ");
Serial.print(state, DEC);
Serial.print(" - availableBytes ");
Serial.println(availableBytes, DEC);
#endif
}
#if debugState
Serial.println("State #2");
#endif
break;

case 3:
availableBytes = Serial1.available();
if(availableBytes > 0){
inChar = (char)Serial1.read();
reveivedData[receiveCounter] = inChar;
receiveCounter++;
if(receiveCounter == bytesToReceive){
state++;
#if debugState
Serial.println("State #3 -> #4");
#endif
}
#if debug
Serial.print("3 Receive remaining bytes");
Serial.print(" - inChar ");
Serial.print(inChar, HEX);
Serial.print(" - receiveCounter ");
Serial.print(receiveCounter, HEX);
Serial.print(" - bytesToReceive ");
Serial.print(bytesToReceive, DEC);
Serial.print(" - state ");
Serial.print(state, DEC);
Serial.print(" - availableBytes ");
Serial.println(availableBytes, DEC);
#endif
}
#if debugStateThree
Serial.println("State #3");
#endif
break;

case 4:
for(outputCounter = 0; outputCounter < receiveCounter; outputCounter++){
Serial.print(reveivedData[outputCounter], HEX);
Serial.print(" - outputCounter ");
Serial.print(outputCounter, DEC);
Serial.print(" - receiveCounter ");
Serial.println(receiveCounter, HEX);
}
state = 0;
#if debugState
Serial.println("State #4");
#endif
break;

// default :
// break;
}

}

/*
SerialEvent occurs whenever a new data comes in the
hardware serial RX. This routine is run between each
time loop() runs, so using delay inside loop can delay
response. Multiple bytes of data may be available.
*/
// void serialEvent() {
// while (Serial1.available()) {
// Serial.println("9 Serial Data Avialable - SerialEvent");
// // get the new byte:
// char inChar = (char)Serial1.read();
// if(receiveCounter == 1){
// bytesToReceive = inChar;
// Serial.println("A Number of Bytes to Receive - ");
// }
// // add it to the inputString:
// // inputString += inChar; //TODO: Remove
// reveivedData[receiveCounter] = inChar;
// Serial.println("B Input Data Read - ");
// // if the incoming character is a newline, set a flag
// // so the main loop can do something about it:
// if ((bytesToReceive - 1) == receiveCounter) {
// stringComplete = true;
// Serial.println("C Completed Input Data Read - ");
// }
// receiveCounter++;
// Serial.println("D End of SerialEvent");
// }
// }





The device returns 35 bytes but the MSP430 device only sees 16 of them. 


2016-08-30+17_04_23-COM5+-+PuTTY.png


 


When I turn off debug (debug = 0) but still output the states (except for state 3) the output looks a lot more acceptable but only runs once. It starts to receive the second set of data but stops at state 3.


 


2016-08-30+17_07_45-COM5+-+PuTTY.png


 


Once debugStateThree is enabled things really stop working. If left this ends up being an infinite loop.


 


2016-08-30+17_10_56-COM5+-+PuTTY.png


 


The data format from the MCP39F511 is a bit odd in that the baud rate is set to 115200 yet the data cannot be sent continuously at that clock speed without breaks, notice the time delay in the send portion of the code, delayMicroseconds(timeSlot); without this the MCP39F511 returns a NACK. Also the returned data is returned in blocks of two bytes.


2016-08-30+17_18_38-Saleae+Logic+Softwar


Data sent to the MCP39F511


2016-08-30+17_20_52-Saleae+Logic+Softwar


 


Data received from the MCP39F511


2016-08-30+17_20_25-Saleae+Logic+Softwar


 


I did attempt to use SerialEvent but that did not seem to run correctly or how I was hoping it would. If anyone can give me some pointers as to what I may be doing wrong and why the code appears to run erratically I would very much appreciate the help.


 


Thankfully 


Kas


Link to post
Share on other sites

Hello @Mention, 

 

I am using the MSP430FR5969 but do to the issues I was going to try it on the MSP430F5529 if this is of any help let me know. I have a few Launchpads that I could potentially test this code on if that helps you in anyway. 

 

Thanks

Kas

Link to post
Share on other sites

Hello @@B@tto

 

A ) the data sent from the MCP39F511 can not be changed, it is set in the IC and I have to deal with it as it comes. I therefore can not look for any special chars.  I do know how many bytes to receive and I am using that but there appears to be an issue with that. A delay in my opinion is bad programing practice and something I would never do if I was using C. Also there does not seem to be an issue if there is no output through the backchannel, at least for the first time through the state machine. The biggest issue is with sending out state 3 that appears to put the system in an infinite loop. 

 

b ) According the Energia reference page the Serial buffer is 128 bytes long: 

 

(Get the number of bytes (characters) available for reading from the serial port. This is data that

Link to post
Share on other sites

Hello @B@tto


 


Thank you for the reply, there are two things that make me think it's may not be a buffer issue. Firstly I only have an issue when the debug is enabled between lines 145 and 159. If the only output is "state #3" there is a critical issue where the system goes into an infinite loop. But, if I enable other debugs and not "State #3" I get less of an issue. The other reason I dont belive it to be a buffer issue is the comment for Serial.available():


 



available()

Description

Get the number of bytes (characters) available for reading from the serial port. This is data that

Link to post
Share on other sites

I just increased the buffer size in "energia-1.6.10E18\hardware\energia\msp430\cores\msp430\HardwareSerial.cpp" to 32, 128 and 256. In all cases the results were the same.


 


Looking at the second line of the compile output "Global variables use..." I can see that when the buffer is set to 16 bytes only about 4% is used but when I change it to 256 it jumps to 58% and if I try 512 I run out of ram. I would conclude the buffer size is increasing but testing this on both a MSP430FR5969 an MSP430F5529 have given me teh same results.


 


The reality is I'm only using Energia because M2X has a library that yo can use without needing an RTOS or other OS. If I could use their C library without needing a RTOS I would happily do so. I may look at other IoT cloud services again to see if I can find another easy to use one that will allow for native C to be used.


 


Kas


Link to post
Share on other sites

I have now reduced the amount of data requested to see if there is anyway the buffer is the issue. The code was changed to request TWO bytes of data. For this there are a total of FIVE bytes returned (header, number of bytes, data[2] and checksum). This would allow for a lot of space in the buffer and should prevent any issues.


 


2016-08-31+14_31_03-Saleae+Logic+Softwar


0xA5 - 0x40 is the data sent to the MCP39F511


0x06 - 0x0B is the data returned to the MSP430


 


2016-08-31+14_32_07-Saleae+Logic+Softwar


Data packet sequence that is sent and returned to and from the MCP39F511


 


2016-08-31+14_34_24-COM5+-+PuTTY.png


As can be seen from the above image this did not resolve the issue (debugState = 1). The program still hangs after receiving the first data received from the MCP39F511.


 


2016-08-31+14_38_49-COM5+-+PuTTY.png


All debugs have been disabled.


 


2016-08-31+14_43_02-Epic+Legendary+Inten


With debug = 1 the program still stops after the first iteration, it starts teh second but teh program does not continue.


Link to post
Share on other sites

Serial.print is non blocking up until the point where you fill the buffer, then it blocks .... one ..... by ....... one.  In the meantime, while processing the incoming data, you're spamming the serial port with state# info and such.

 

Would it be possible for you to signify stateful information by toggling a GPIO or 2?  Capture that with your Saleae and you'll have a debugging/reporting mechanism that's way less time-critically-intrusive.

Link to post
Share on other sites

Better yet in fact, if you choose a GPIO say, P3.0, set it up using pinMode(pinnum, OUTPUT); and then toggle it using the P3OUT register directly:

 

P3OUT |= BIT0;

P3OUT &= ~BIT0;

// ^ only once for state #1

 

P3OUT |= BIT0;

P3OUT &= ~BIT0;

P3OUT |= BIT0;

P3OUT &= ~BIT0;

// ^ did it twice for state #2

 

etc

Link to post
Share on other sites

The answer I found in my last post. Thanks to peteroakes? suggestion of trying less than 16 bytes I was able to see that the receiveCounter value a bit clearer. If you look in the last picture in teh above post the counter counts up to 0xA but there are never more than 5 bytes in the packet. This led me to realize the counter was not being reset and as such the once the first set of data was received the condition to ignore receiving more data was always true. 


 


As of this writing the program has been pulling data over serial for almost 3 hours even though its only been 5 bytes and not the 35 or so I will hopefully get working later.


 


Kas


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...