I need some help finding the documentation of .read(). I know this is easy, but I can't find it. I've search and searched, and this page on the android side is the closest I could find - http://developer.android.com/guide/topics/usb/accessory.html.
Here is the arduino code splice I am trying to interpret. I need to know how to modify the read() part for my needs. Thanks
AndroidAccessory acc("Manufacturer",
"Model",
"Description",
"1.0",
"hey.now.what",
"0000000012345678");
acc.read(msgIn, sizeof(msgIn), 1)
I was looking the same thing as you did. After googling around and trying it by myself, I managed to build up something like this:
Declaration:
int AndroidAccessory::read(void *buff, int len, unsigned int nakLimit);
Reads data from the Android device into the array pointed to by buff. It reads len number of bytes. Reading is stopped when len bytes is read or nakLimit number of NAKs is received from the USB controller. In case of Full Speed USB a NAK will be generated every 1ms. (according to the second source link).
The return value is the number of bytes available, not the number of bytes read. If you read less bytes than there are available, those extra bytes seem to be ignored.
In my experiments I found out that NAK interval is much smaller. With my Arduino Mega ADK, I found out that one second wait equals roughly nakLimit of 14000.
Sources:
http://developer.android.com/guide/topics/usb/adk.html (end of the page)
What is Nak Limit?
Related
I am working on a group project where we are sending serial data over Bluetooth from Arduino to Android. We are all fairly new at both Arduino and Android.
Hardware used include Arduino Uno R3 and HC-05 bluetooth module.
I am sending dummy data for a 3 axis accelerometer packet and successfully read the packet data from Android.
However, we have this blob of data (about 50+ bytes usually and has ranged up to 512 bytes) that always gets sent to the app in the beginning. Its a randomly sized chunk of bytes, which we can't interpret because it doesn't seem to match the packet format we set up for our data. We managed to avoid looking at this byte chunk by checking to see if the packet size is small enough. But this adds a lot of overhead (4 - 5 seconds), so we'd like to figure out what this blob of data is. So, does the HC-05 send some proprietary Bluetooth related data first or is there some thing wrong with my script that's causing the unexpected data to be sent?
This is the Arduino code.
#include <SoftwareSerial.h>
SoftwareSerial bluetooth(10,11);
void setup(){
bluetooth.begin(9600);
}
void loop() {
int x = random(360);
int y = random(360);
int z = random(360);
formAccelerometerPacket(x, y, z);
delay(5000); // wait 5 sec
}
void formAccelerometerPacket(int xVal, int yVal, int zVal) {
printSensorVal('A', xVal);
printSensorVal(':', yVal);
printSensorVal(':', zVal);
}
void printSensorVal(char flag, int sensorVal) {
bluetooth.print(flag);
bluetooth.print(sensorVal);
}
I've looked at it with a Bluetooth terminal app but nothing looks wrong from there. Its LogCat from the app that shows this content received from the app, but I can't interpret it as I said earlier, which is what I need to solve.
I've tried to look at other SO questions but none others could help me.
I don't have the code for the Android app as it is with another teammate, but I know that they followed the BluetoothChat example closely.
The only thought I had was that since Arduino loops the data, if the app starts after the Arduino starts, it might start reading some data part way from what was going on in the serial port before. But it doesn't explain the size difference in the blob of bytes.
Edit on 08/21/2014 at 10:33AM PST
Here is a screenshot of the LogCat. What we did was ran the Android app first and then I started the Arduino to make sure the board didn't have old data. Looking at this makes me think it might be a pairing issue as some one suggested. I am working on trying that fix.
Try Bluetooth SPP on Google Play, then connect to the HC-05. Check the output and then once you get clean data reset the arduino and see what happens. That's how I usually go about checking the output from my HC-05. And no there is nothing sent by the HC-05 when it starts up. I couldn't comment so had to post an answer, sorry.
I am not sure that is your case but may be it's usefull. When you send a data from HC-05(FC-114) to a Slave(HC-06) the first byte(or the first three/four) is sent immediatly and the rest with a delay of 5/10ms. I don't know why, but i see it using oscilloscope. If well managed, you can fix the problem when receive the packet of byte waiting for a while, otherwise, you can get crazy for understand what is happening.
I'm experiencing a strange behavior of bluetooth socket (in my opinion), and I would like know if anybody can clarify it to me.
The situation:
I have two Android applications connected together by a Bluetooth socket:
The first makes a simple write(byte[] message) on the output stream.
The second makes a simple read(byte[] buffer) on the input stream.
On the reader side I use a buffer of 1024 bytes. The sender send a message a little bit larger than the receiver buffer size: 1024 + 108 bytes (always the same message).
Ok now the behavior:
On the reader app I receive the most often a first chunk of 1024 bytes which fills up the buffer (as expected) and then a second one of 108 bytes.
But really often (maybe 40% of the time) I receive a first chunk of 1008 bytes and then a second one of 124 bytes.
I really would like to understand this because I'm affraid to miss an important bluetooth concept. At first I was thinking to compare the count of byte read with the buffer size to know if the entire message had been received but this experimentation shows that it's maybe not a good idea.
Is anybody can explain to me this behavior?
Thanks in advance.
For the record, I now use Google Guava methods for read/write on streams and all works fine.
I'm finding the same thing- it seems to be because Bluetooth sends data over as a stream instead of packets.
So if I send 4 500 byte packets, it might end up sending a 1600 byte one and a 400 byte one, or the way I sent it. Over stack overflow questions say to use some random value in the byte array to tell when a message is finished (How to read all bytes together via Bluetooth?).
There should be a better way, but I plan to use a very unlikely character set to try to find the end of the message- and pad it onto the end of each of my messages going out. Some of the other stack overflow questions suggest using '\n', but I might end up using several to make it more unlikely, such as: "\t~\t"- something that should never be typed in my game (or hopefully not extracted from the enormous amount of other stuff going on).
Hope that helps!
I am writing software to communicate between tablet (Motorola Xoom with Android version 4.0.3 and Kernel version 2.6.39.4) and a peripheral device using USB Host API provided by Android. I use only two types of communication:
control: controlTransfer(int requestType, int request, int value, int index, byte[] buffer, int length, int timeout)
bulk: bulkTransfer(UsbEndpoint endpoint, byte[] buffer, int length, int timeout)
Control transfer works fine, but I have a problem with bulk transfer. I can use only 32768 as a size of the buffer for bulkTransfer function. It is not possible to use less or more. I know that I cannot use more because of the limit of the buffer pipe (size: 32769 bytes).
This peripheral device streams data which is not correctly read by bulkTranfer function. I suppose that some data is lost.
I find this: In Linux If a process attempts to read from an empty pipe (buffer), then read(2) will block until data is available. If a process attempts to write to a full pipe , then write(2) blocks until sufficient data has been read from the pipe to allow the write to complete.
And based on that, my explanation of the problem is that some data is not written to pipe (buffer) because of blocking flag made by write(2) function. Am I correct? If this is true I could change pipe buffer.
My first solution for this problem is greater buffer. For
kernel >= 2.6.35, you can change the size of a pipe with fcntl(fd, F_SETPIPE_SZ, size) but how can I find fd (file descriptor) for
USB pipes?
Second option is to use ulimit -p SIZE but parameter p for my kernel is not for pipe but process.
Has anyone faced the same problem, any solutions?
You should get a USB data analyzer, Im using this one: http://www.ellisys.com/products/usbex200/index.php
Using something like this really helped me when I was doing the same type of thing, what I found was that you had to do some type of while loop.
For my device I had 64 bytes of data coming in packets to me, the packet would be two control bytes and 62 for data, so for my transfer I had to do something like
StringBuilder sb = new StringBuilder();
while(bulkTransfer(UsbEndpoint endpoint, byte[] buffer, int length, int timeout) > 2){
for(int i = 2; i < buffer.length(); i++){
sb.append((char) buffer[i]);
}
}
something a long these lines worked good for me, i had exactly the same issue and this is how I fixed it. I have more information if you need it. Just comment :). I know this was really frustrating for me to. Im using an Acer Iconia A500 with Android 4.0.3 btw
Transferring larger amounts of data USB
Transferring data USB
According to the same .pdf gfour posted, I found this paragraph in there:
"The size of the packet will affect the performance and is dependent on the data rate. For very high speed, the largest packet size is needed. For 'real-time' applications that are transferring audio data at 115200 Baud for example, the smallest packet possible is desirable, otherwise the device will be holding up 4k of data at a time. This can give the effect of 'jerky' data transfer if the USB request size is too large and the data rate too low (relatively)."
I'm running into a situation similar to SmartLemon with a FTDI Serial device, so I've been recently looking up ways to alleviate it. This will require me to pretty much write my own functions from scratch while previously I was using a library.
However, it seems that in your case, you could try using bulkTransfer's lowest buffer size instead of shooting for the biggest. You may have tried this already, but maybe not. I see that you say 32768 is the only size, but maybe you only meant the max. It seems weird that it'd only allow one specific size.
The Android SDK's UsbEndpoint object provides a getMaxPacketSize() method, allowing you to check what is appropriate for your device. Generally, the maximum allowable packet size is 64 bytes for USB 'Full-speed' devices and 512 for 'High-speed' devices - far less than 32,768 you are attempting. Are you perhaps confusing the underlying USB packet size with that of some higher-level protocol?
According to AN232B-04_DataLatencyFlow.pdf, flow control is needed for high data rates:
It is strongly encouraged that flow control is used because it is
impossible to ensure that the FTDI driver will always be scheduled.
Have you tried using one of the flow control options (RTS/CTS, DTR/DSR, XON/XOFF) to synchronize your data?
You can try this for Bulk transfer issue
byte[] buffer = new byte[4096];
StringBuilder strIN = new StringBuilder();
if (conn.bulkTransfer(epIN, buffer, 4096, 500) >= 0) {
for (int i = 2; i < 4096; i++) {
if (buffer[i] != 0) {
strIN.append((char) buffer[i]);
textReceiveDataInfo.append(strIN + "\n");
} else {
l(strIN);
break;
}
}
}
Am trying to understand how the Android Open Accessory API works with the Arduino ADK board, I've been able send and receive information but I just want to know how everything works. I got to this function description:
int AndroidAccessory::read(void *buff, int len, unsigned int nakLimit) {
return usb.newInTransfer(1, in, len, (char *)buff, nakLimit);
}
From some googling I figured that NAK is some code that gets sent if something went wrong during the handshake, so is NAK limit the number of communication errors one is able to receive?
NAK is no Communication error. It simply states that the Device is not ready to send a reply or that there are no data to send at this moment. As I understand it the NAK limit in this function will just make sure that there's a defined end for the function. In case of Full Speed USB a NAK will be generated every 1ms. For more information about the NAK try this: http://www.beyondlogic.org/usbnutshell/usb3.shtml#USBPacketTypes
To read data from an opened USB connection one uses UsbDeviceConnection bulkTransfer method.
I have the situation that after sending a request the routine should read all incoming data, which can be just 8 bytes or even 300+ bytes.
The problem is that bulkTransfer does not read all the bytes for some reason - it just returns with some bytes while there could be more to come.
Is it better to write a loop around bulkTransfer until there is no more data, or increase the timeout, or possibly there is another approach.
What would be the best way to handle this?
I tried the loop approach and I am surprised that it only reads about 10-20 bytes each time with a timeout of even 1second. I am sure there is more data already available, don't know why it does not read more at a time.
Does it matter which buffersize one uses - many examples have 4096 but how does changing this influence the reading of data?
Many thanks
If the device sends 10 bytes at a time and does so repeatedly to finish the 300+ bytes, you still only get these 10-byte chunks each time you read with bulk transfer.
In other words, the method does not wait to fill up your buffer. It returns as soon as there is something. So if you really want to collect the entire 300+ byte response, you do need to loop.