2017년 3월 30일 목요일

Reading more then ONE serial data object (serial.println) from arduino


I have asked this same question before but got stuck and the question was closed a few days in advance and I cant open it any more. I left it for a while then got hospitalized and now recovered to start over again.

From an arduino I get 4 pieces of data send by serial.println function.
It looks like 
A,123
B,456
C,789
D,012
So always a letter fllowed by a comma and then a value.

I need to get this data into four labels.
From this data 5 other labels need to be calculated bu that is for a later stage.
But my important task now is to get more then one (1) piece of serial data to the appropiate label.
The suggested sample codes I got before do not to get to work at my side.

For you information I can connect to a bluetooth serial com and send data from the Phone to the arduino.
So that piece of code is working but receiving more then one is a problem.
If have something created in BLOCKS but that does not work for reading into a serial buffer then split the buffer date and send the correct data value to the correct data label.
If I can get an example that does 2 pieces of data to two individual labels I think I can create the other two by myselve :-)
But your assistance is needed and I assume I am not the only one who is in need for this kind of data gathering coming from an Arduino based device.


--
Is the value always 3 characters and how many times are you receiving the data, just once or continuously?

Do you have control over the format of the data?

--
Hi, I am trying to find out about bluetooth communication myself, therefore I do not have a complete answer.
I am wondering however, if you are recieving any text at all and whether this text is what you expect it to be.
Maybe splitting it into 4 parts is the least of your problems, first make sure that you receive the right thing.
The way to do this is to have a clock and at each Timer event see if there is text to recieve, like in this example:
Then, when you are sure that you get the correct text, I can help you to split it the right way. This will be a combination of using lists and text blocks.

-- 
If you can build up your four values into a JSON string on the Arduino side
and transmit it in one shot, AI2 has a nice Web block that can decode 
a JSON string and pull out named values from it.
You don't need a Web connection for this, just the Web component.

See attached for an example.



-- 
Hi and thanks sofar for your thinking with me and the cooperation,

More info,

Data at arduino side is fully adjustable to some extend (my knowledge).
I have to read four loadcells continously (balance weigth scale) and if the display at the APP side interval is 1 second I am happy.
Values vary in character number so cant split on that.

I am not known to JSON strings have to check if that is possible at arduino side.

General operation should be:
I have to put the data in a buffer.
Then at 1 second interval read the buffer?
Then if the buffer has 30 characters put it in a label in my example label 11 as general gathering label;.
Then split the data from the label 11 into the letter and data parts and put them in 4 seperate labels called label 1 to label 4 and the letter removed.
So easy in words................;-)


-- 
If I look at your Arduino program, it seems that it would be easy to use the "list from csv table" block, because you will recieve a string such as: "A, 123\nB, 234\nC, 456\nD,567". That would give you a list of 4 elements, and by looping through you can assign each to a label.

But, what you should do, as I said before, first check out what you really get and check whether that is what you expect. Put the whole string in one label for the time being and get that working, using my example above. Only then start splitting your strings.

-- 
I don't have examples to show but I do have several apps that work with Arduinos, sending and receiving data. There are probably many different solutions to this. Mine would be to convert the values to ascii before sending to the app. This would give the data a fixed size which makes it easier to work with within the app. It also means you do not really need the commas. Data would be "A123B456C789D012" (no quotes) and can be sent as a single string from the Arduino. On the app side I would wait until I have a full data set before starting to process it.

When receiving the data in the app, I use global buffer variable and timer. Inside the timer tick block, I check for new data (using bytes available) and if available add it to the global buffer. I then process the buffer.

check the buffer
- if the buffer contains an "A", check to see if the buffer starts with an "A"
       - if the buffer does not start with an "A" remove the first x characters until the buffer starts with an "A".  Anything before an "A" can be ignored.
- then check the buffer size. If the buffer length is 16 or more you have a full data set.
        - take the first 16 characters and process. Leave the remaining data in the buffer.
        - process the data.

For complex data sets I also enclose the data in start and end markers (I generally use < and >). This allows me to easily check that I have a complete data set. I simply check the buffer for the "<" and ">" characters.

--
I have to get the hardware ready (undust it first)
I have a basic app recreated from this link

Will check tomorrow what kind of data I get in label1
.
If possible I will try to record it.

But to be clear.
You cant expect that serial data received is always the same length or at the same time received.
Therefor a buffer is needed and from there the data need to be reworked like MartynC explains in words.

My windows based program that is already working fine needs the mentioned data with the comma as that is the delimiter for spliting from the buffer there.
Now I can also send the data for the APP in an other format as extra the way for the APP to work more esy on it. 

Let you guys know asap what label1 is showing.

--
Yeah. I saw that tutorial. Youtube is hard when no .aia is attached.
Here is a very basic bluetooth client, I found (from a chat app, it was in Italian, I cannot find the source back to give it proper credit).

p.s. I am not a guy as you could see from my avatar.


--
This post gave me the motivation to create a basic Bluetooth app/template. Something I have been meaning to do for a while. This represents my usual method of handling Bluetooth communication with an Arduino/AVR + Bluetooth module and is the basis for my apps that connect to an Arduino. The Arduino has to be paired with the host Android device before the app can connect to it.
App Notes
I use a button to activate a list picker. When the button is clicked I copy the paired devices to a list before I copy to the listpicker. Using a list allows me to check how many paired devices there are and display a warning if there aren't any. Using a button also gives an easy way to allow the user to disconnect.
Data is contained within start and end markers, I normally use :<" and ">".
I use a timer to check for incoming data and any new data is added to a buffer.
I then check the buffer for the start and end markers. If I have both I know I have a complete data set. I would not normally process data until I get a complete set. I ignore anything not inside the start and end markers
The processIndividualDataElement function handles processing the data. In the example I simply copy the data to a label but you can whatever you like based on the data received.
When receiving a lot of data quickly I find it better to trim the buffer and remove any characters to the left of the start marker (or the first start marker). This is not required when there is not much data or the update is not very frequent.
It is possible that I have more than one data set and so inside the processIncommingData function I loop through the buffer until the buffer does not contain both the start marker and the end marker.
The app can be more robust and I would normally have additional error trapping but I think it can serve as a good foundation for developing a more complex app.
Arduino Sketch
The Arduino sketch also expects data to be enclosed in start and end markers. The sketch keeps checking serial in (I am using software serial in the example) and copies it to a receivedChars global variable. Once I have a complete code I invoke the processData() function.
Circuit.
An Arduino with a Bluetooth module (HC-05/HC-06 or similar). I am using software serial on pins D2 and D3 to talk to the BT module. Hardware serial is used for the serial monitor. Sent data and received data is copied to the serial monitor.




--
Sorry I might have overlooked your avatar and missed your a codinggirl ;-)
I dont mind, it is the code that counts :-)
I just checked the basic .apk on my mobile phone and it sends data to the label but like I susected the first line of the label can be anything of the code that is coming from the arduino.
Sometimes it is spot on and at every /ln but sometimes I just see a letter and no traling value sometimes only a value.

@ Martyn,

Swell for sharing this information. I think many other will benefit from it. On arduino and MIT side I have to check if I understand what is going on in large and in small details.
I see the number of blocks is much more then I expected.

I will first experiment with your .aia and .ino and see if Iater I can implement it in my project code.
But I already have a first question for my understanding.



void sendData(byte c)

{   

    digitalWrite(13,HIGH);
    if      (c==1) { BTserial.print("<A123B456C789D012>"); Serial.println("OUT - <A123B456C789D012>"); }
    else if (c==2) { BTserial.print("<A987B654C321D098>"); Serial.println("OUT - <A987B654C321D098>"); }
    else if (c==3) { BTserial.print("<A111B222C333D444>"); Serial.println("OUT - <A111B222C333D444>"); }
    delay(50);
    digitalWrite(13,LOW);
}

if      (c==1) { BTserial.print("<A123B456C789D012>"); Serial.println("OUT - <A123B456C789D012>"); }

can I make this of it too?

value1 = A123456
value2 = B123456
value3 = C123456
value4 = D123456

SvalueOut = value1 + value2 + vaue3 + value4

if      (c==1) { BTserial.print("<SvalueOut>"); Serial.println("OUT - <SvalueOut>"); }

So only one line and 4 values (no floats) of 6 digits?

--
the sendData function can be changed to whatever you want and you do not need c. In the example I use c to change the test data so that you can see movement. When test data is static (the same value every time) I find it hard to spot problems.

Anything to Serial.print is for debugging. For example { BTserial.print("<A123B456C789D012>"); Serial.println("OUT - <A123B456C789D012>"); } lets me know I have sent data to the app. This is handy when developing new sketches and can be removed once everything works.

For use with a sensor I would normally do something like:

1 - read sensor value
2 - check the value is OK (in range etc)
3 - convert the value to a char
4 - set the size of the char (for example '27' becomes '000027')
5 - add code and start and end markers (for example '000027' becomes '<A000027>')
6 - send the char/string

Here is my function for converting numbers to formatted strings. It is one of many different ways to do this. The function uses a global variable called numberString.
To use you would call the function with formatNumber( 123, 6). This would put '000123' into numberString. 

void formatNumber( unsigned int number, byte digits)
{
    char tempString[10] = "\0"; 
    strcpy(numberString, tempString);
 
    // convert an integer into a acsii string base 10
    itoa (number, tempString, 10);
 
    // create a string of '0' characters to pad the number    
    byte numZeros = digits - strlen(tempString) ;
    if (numZeros > 0)
    {
       for (int i=1; i <= numZeros; i++)    { strcat(numberString,"0");  }
    }
    strcat(numberString,tempString); 
}

If using multiple sensors, perform the above steps for each sensor. You do not need to join the data from each sensor. You can send each sensors data separately as you get it.
I would suggest you start with a single sensor, get it working and then add more.

Have a look at the sketches at arduino-bluetooth-control. These should give you more ideas.

--
@Martyn Thanks a lot for sharing this.

-- 
Your welcome

--
For my convenience I took the 003 sample Martyn has on his webpage and installed the ABC app.
When I connect the BT to the Android I can see the Analog pin value is changing by touching the pin that is connected to the analog port.

Then in the arduino sketch I added and declared integer value called ValueOut1
in void checkPins()
I also added ValueOut1 = 1023; as a static value to be dislayed.
I changed the line.

 // Check the value on analogue pin A1
  newPotVal = analogRead(A1); to newPotVal = ValueOut1;

I connect BT again but the ABC app does not see any value change and stays at 0000 instead of 1023

Do I think wrongly to replace the analog port value for a integer valeu?

Paco

BTW my test unit with 4 loadcells and BT modul is attached.



--
It sounds like the value you are sending is not what you think it is or you are not actually sending anything. Use the serial monitor to check what value newPotVal has. 
The sketch has a basic debugging aid. Turn this on and open the serial monitor.

// Change DEBUG to true to output debug information to the serial monitor
const boolean DEBUG = true;
~
~
~
if (DEBUG) { Serial.print("[A01"); Serial.print(numberString); Serial.println("]"); }

You can also send the value by directly putting it in to the command, for example [A011023]


If adapting the sketch, I would suggest using your own variable names, change potVal to something meaningful. You should also strip away everything you don't need.

If you are still having problems leave me a message on the website. Not sure how much we can discuss none ai issues on this forum.

--
Martyn,

I left a message at your website.
Once were done I get back here for the MIT2 app created.

--

댓글 없음:

댓글 쓰기