Kazz 0 Posted August 30, 2016 Share Posted August 30, 2016 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. 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. Once debugStateThree is enabled things really stop working. If left this ends up being an infinite loop. 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. Data sent to the MCP39F511 Data received from the MCP39F511 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 Quote Link to post Share on other sites
energia 485 Posted August 30, 2016 Share Posted August 30, 2016 Hi @@Kazz, thanks for reporting the issue and thanks for the detailed report! What LaunchPad do you have selected? Knowing which device will help me a lot in an attempt to reproduce it. Quote Link to post Share on other sites
Kazz 0 Posted August 31, 2016 Author Share Posted August 31, 2016 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 Quote Link to post Share on other sites
B@tto 51 Posted August 31, 2016 Share Posted August 31, 2016 Hi, Kazz, you should take in consideration this three things : 1) Serial is slow compared to a Quote Link to post Share on other sites
Kazz 0 Posted August 31, 2016 Author Share Posted August 31, 2016 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 Quote Link to post Share on other sites
Kazz 0 Posted August 31, 2016 Author Share Posted August 31, 2016 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() DescriptionGet the number of bytes (characters) available for reading from the serial port. This is data that Quote Link to post Share on other sites
Kazz 0 Posted August 31, 2016 Author Share Posted August 31, 2016 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 Quote Link to post Share on other sites
Kazz 0 Posted August 31, 2016 Author Share Posted August 31, 2016 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. 0xA5 - 0x40 is the data sent to the MCP39F511 0x06 - 0x0B is the data returned to the MSP430 Data packet sequence that is sent and returned to and from the MCP39F511 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. All debugs have been disabled. With debug = 1 the program still stops after the first iteration, it starts teh second but teh program does not continue. Quote Link to post Share on other sites
spirilis 1,265 Posted August 31, 2016 Share Posted August 31, 2016 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. Quote Link to post Share on other sites
spirilis 1,265 Posted August 31, 2016 Share Posted August 31, 2016 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 Quote Link to post Share on other sites
spirilis 1,265 Posted August 31, 2016 Share Posted August 31, 2016 Actually another idea could be to use SPI, transmitting debug info over SPI would be loads quicker than Serial UART and you could get full bytes of information sent that way. Pick it up with the logic analyzer and use the protocol decode feature in the software. Fmilburn 1 Quote Link to post Share on other sites
Kazz 0 Posted August 31, 2016 Author Share Posted August 31, 2016 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 Quote Link to post Share on other sites
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.