Unpack array of integers from a bluetooth socket - android

I'm currently working on a PiBot project in Python (chassis with 4 wheels, controlled by Android app via bluetooth for now).
I made a prototype in Python, i can create a BT server, subscribe to it and pair the device via Android, and send information through the BT socket : a joystick gives me the strength and angle on Android, and i succesfully read them from the server. I use Struct for decoding the integers array from the stream bytes.
Here's a piece of my BTServer class, the loop where i display values on server :
def goToControls(self):
while True:
data = self.client_sock.recv(1024)
size = len(data)
print size, 'bits'
try:
angle, strength = struct.unpack('>ii', data)
print angle, strength
#self.cHandler.move(angle, strength)
except struct.error:
print 'bad scheme...'
On Android side, the function which sends data :
if (btDevice.getMmSocket().isConnected()){
int[] values = {angle, strength};
ByteBuffer byteBuffer = ByteBuffer.allocate(values.length * 4);
IntBuffer intBuffer = byteBuffer.asIntBuffer();
intBuffer.put(values);
byte[] array = byteBuffer.array();
try {
btDevice.getMmSocket().getOutputStream().write(array);
btDevice.getMmSocket().getOutputStream().flush();
} catch (IOException e) {
e.printStackTrace();
}
}
Here's my console output, from server :
So it works great. As soon as i uncomment the line self.cHandler.move(angle, strength), which gives data to my controls handler and make wheels turn, or if i replace it with anything, such as a time.sleep(0.1), here's what i get :
It looks like the scheme is changing, i can't understand anything... Has someone got a clue ?
Thanks a lot
-- EDIT :
I found a part of the answer : I was trying to send 8 bytes from android and receiving 1024 from struct.
So I changed it for that :
data = self.client_sock.recv(8)
angle, strength = struct.unpack('>ii', data)
print angle, strength
self.cHandler.move(angle, strength)
And it works, but it's now terribly slow. How can I decode those 8 bytes without slowing the process like this ?

Related

Bluetooth Low Energy (between ESP32 and Android smartphone): Data transmission quite slow

This is my first question ever asked on this board
The project explained short:
5 sensors, connected with an esp32 board are transmitting 1000 samples/second, each sample has 16 bit. Those values should be transmitted via BLE (With the BLE Arduino library and an ESP32). The connected device (Smartphone) should read those values and do something with them (Also via BLE, with the following library: https://github.com/RobotPajamas/Blueteeth). The ESP32 is the Server! Java is used in Android Studio!
The problem:
While testing the BLE connection a simple "hello world" was transmitted as the value for a characteristic. Every time i received the "hello world" on the android-device-side, a variable was incremented: The problem is, the variable only got incremented 4 times in one second. This means (assuming 1 char in a string equals 1 byte) 11byte*4(1/s)=44byte/s are being transmitted. -> This clearly is not enough (should not BLE transmit ~2MBit/s (minus the protocol-data))
Code Fragments
ESP32: BLE-Server that transmits value
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
class MyCallbacks: public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) {
std::string value = pCharacteristic->getValue();
if (value.length() > 0) {
Serial.println("*********");
Serial.print("New value: ");
for (int i = 0; i < value.length(); i++)
Serial.print(value[i]);
Serial.println();
Serial.println("*********");
}
}
};
void setup() {
Serial.begin(115200);
BLEDevice::init("MyESP32");
BLEServer *pServer = BLEDevice::createServer();
BLEService *pService = pServer->createService(SERVICE_UUID);
BLECharacteristic *pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE
);
pCharacteristic->setCallbacks(new MyCallbacks());
pCharacteristic->setValue("Hello World");
pService->start();
BLEAdvertising *pAdvertising = pServer->getAdvertising();
pAdvertising->start();
}
void loop() {
// put your main code here, to run repeatedly:
delay(2000);
}
Android Studio Code (Snippet of the receiving source):
try
{
while(sampleBluetoothData)
{
this.selectedDevice.readCharacteristic(MainActivity.characteristicUUID, MainActivity.serviceUUID, (response, data) ->
{
if (response != BlueteethResponse.NO_ERROR) {
return;
}
Log.d("AUSGANG", new String(data) + "times: "+ i);
i++;
});
}
}
catch (Exception e)
{
e.printStackTrace();
}
The write on the ESP32 side is a blank example code of the Arduino IDE, the read on the Android-side is made by the BLE-Library publisher. Yes the Log.d effects the performance, but it does not drop it that much.
The variable "data" of the Android code is the received char-array. The bluetooth-reading runs on a background thread.
Question I ask myself now:
Is the Android-Studio library the problem or the Arduino library
Is this a normal behaviour, that if a value of a characteristic does not change, it is being transmitted quite slowly.
How fast can you update a value of a characteristic
Thank you in advance!
BLE can definitely transfer much more than 4 portions of 11 bytes per second.
Approach of reading:
Generally, continuos reading all the time is NOT the expected BLE way - it's better to subscribe to data changes, so ESP32 will notify only when needed (e.g. do selectedDevice.subscribeToCharacteristic once, instead of reading in a loop, but then ESP32 code should be changed accordingly)
I guess selectedDevice.readCharacteristic requests asynchronous BLE read, and when you call it in while(sampleBluetoothData), your Bluetooth library is adding more and more read requests. Maybe it would be wise to request new read only after the previous read is done - in read callback add if(sampleBluetoothData) { this.readAgain(); }
Consider making a testing prototype from this kickstart example: BLEProof on github - Android & ESP32, read, write, notify (but it uses just system API without Bluetooth library, you approach is better, it's easier and safer to use the library).
What else to check:
Android side: are you sure that your code doesn't go inside of if (response != BlueteethResponse.NO_ERROR) ?
Android side: to ensure Bluetooth library is not overloaded with read requests, try adding a delay 50 milliseconds in the reading loop (just to check, it's not a solution)
Android side: are you sure that you don't have other BLE read/writes while you read those data?
ESP32 side: use shorter BLE connection interval (BLE throughput article) - add pAdvertising->setMinPreferred(0x06); and pAdvertising->setMaxPreferred(0x20); before pAdvertising->start(); (but that sets only "preferred" interval, Android may ignore that)
Using read requests, you are mainly limited by the connection interval for transfer speeds - that is 2 intervals for request + response.
If for example your client has a connection interval of 50ms, you should expect to read a characteristic of up to 20 bytes 10 times per second.
If another client has a connection interval of 30ms, this rate improves to 16.6 reads per second.
The fastest negotiatiable connection interval is 7.5ms for a maximum of 66.6 reads per second (10.7kbps with 20 byte reads).
I was reading BLE wikipedia page and the minimum data rate is 125Kbit/s , so I think that in your case is viable, because you only will transmit 16Kbit/s. Take a look in BLE wikipedia.

Android via NFC IsoDep(ISO14443-4) communication with chip's FIFO cache area no way to more than 12 bytes

I'm pretty troubled with android NFC transacting with chip's FIFO cache area. Another side(B) and android app(A): B was electrify to chip,and B write data to chip's FIFO cache area by C language. The chip's FIFO cache area can not save data after outage, and when chip's FIFO cache area send all data, the chip's FIFO cache area will clear.
The situation is, A close to chip, send a APDU command, now chip receives the command and produces a signal. Then, the B detects the chip's signal, and grabs the command, then, B gets the command's first byte(fb), more then, B write [fb+data+9000] to chip's FIFO cache area. Finally, the transaction of send data back to A manage with chip self and we don't know the chip how to manage the send back.
The problem is, when B's write [fb+data+9000] less than 15 bytes(means data only 12 bytes), A can receive the [fb+data+9000] from chip. But the [fb+data+9000] more than 15 bytes, A throws TagLostException.
The chip use ISO14443-4 protocol.
The command:
The transact code:
`
try {
isoDep.close();
isoDep.connect();
}catch (IOException e){
errorfound = true;
onMessageReceived.onError(e);
}
if (!errorfound) {
if (isoDep.isConnected()) {
try {
isoDep.setTimeout(1200);
response = isoDep.transceive(newtest1_apdu);
int status = ((0xff & response[response.length - 2]) << 8) | (0xff & response[response.length - 1]);
if (status != 0x9000) {
log.error("retrieve data ,read failure");
}else {
log.info("retrieve data, result=" + numeralParse.toReversedHex(response));
}
onMessageReceived.onMessage(response);
}
catch (TagLostException e) {
log.info("catch tag lost exception, tag isConnected=" + isoDep.isConnected());
onMessageReceived.onError(e);
}
catch (IOException e) {
log.info("catch IOException, isoDep isConnected=" + isoDep.isConnected());
onMessageReceived.onError(e);
}
}else {
log.error("isoDep not connect");
}
}
`
Android app(A) try to a variety of commands, contains this format: .
And another side(B) only gets first byte in command and write [fb+data+9000] to chip's FIFO cache area. this isn't timeout reason, except setTimeOut(1200), also try setTimeOut(5000) or not setTimeOut. Other, A and B were not appoint the APDU command specific meaning. Other, by different APDU command, A work well with read Public transportation card(may be this read to block area, and now work with cache area, both work way not same). Other, the configuration of chip is basic default. Other, with other card reader test, chip's send data out success.
I go to Google,Bing,Baidu,Android office issues,stackoverflow and so on to search answer, but cannot find. This problem very bothered us. Apologetic with my poor English. Please help, extremely thank you.
(the chip is FM11NC08.)
New progress, We found, giving up using APDU command, if A send 1 byte, A can receive maximum 16 bytes. And if A send 2 bytes, A can receive maximum 15 bytes. And if A send 15 bytes, A can receive maximum 2 bytes. The chip's FIFO cache area has 32 bytes space. After B receive A's data, B will clear FIFO cache area, then write data to FIFO cache area.
Thanks in advance.
Today, B changes the chip's communication rate(from 1M to 2M) and a part of codes. Then A work well with chip! So, we found the communication rate has an impact on NFC communication. If you have the same trouble with NFC communication, might to try our way!
Thanks for people who consider this problem in not-solve days.

Pic16F688 has no stable readings via buletooth

I have spent much time trying to find out where is my mistakes while Im flashing the PIC16F688. The Pic has successfully flashed using PicKit2. Im using the Pic to convert analog pressure sensor to digital output and sending the data via Bluetooth, but the Bluetooth is not receiving stable numbers of data. The data is consist of 4 character decimal number that is between 0 and 1023.
The problem is that the Bluetooth can't wait at specific number and keep reading it, instead, it is reading the 4 digits in random.
I think my mistake is within the configuration of internal oscillator.
I'm attaching my code, the code is written to configure the flexiforce sensor circuit that outputs analog voltage up to 5v, and then the pic duty is to convert it to digital as I mentioned above.
it might be my wiring is not correct, please If you could help out with this one
and what configuration "at edit project" do I need to choose for Mikro PRO software?
I used "Bluetooth terminal" app to see my data asynchronous from Bluetooth.
Thank you.
char *temp = "0000";
unsigned int adc_value;
char uart_rd; int i;
void main()
{
OSCCON = 0x77;
ANSEL = 0b00000100;
CMCON0 = 0X07;
TRISA = 0b00001100;
UART1_Init(9600);
Delay_ms(100);
while (1)
{
adc_value = ADC_Read(2);
temp[0] = adc_value/1000+48;
temp[1] = (adc_value/100)%10+48;
temp[2] = (adc_value/10)%10+48;
temp[3] = adc_value%10+48;
for (i=0;i<4; i++)
UART1_Write(temp[i]);
UART1_Write(13);
Delay_ms(1000);
}
}
You can use itoa function to convert ADC integer value to characters for sending over UART. If there is error in calculation then you wont get appropriate value. Below code snippet for your reference :
while (1)
{
adc_value = ADC_Read(2);
itoa(adc_value, temp, 10);
for (i=0;i<4; i++)
UART1_Write(temp[i]);
UART1_Write(13);
Delay_ms(1000);
}
Please check Baud Rate you have configured at both ends is same or not. If baudrate mismatches then you will get Random value at Bluetooth Terminal where you are reading values.
What i would suggest, if you have a logic analyser, hook it up. If you don't recalculate your oscillator speed with the datasheet. It could just be that the internal oscillator is not accurate enough. What also works, is to write a function in assembly that waits a known time (by copy-pasting a lot of NOPs and using this to blink a led. Then start a stopwatch and count, say, 100 blinks. This is what i used to do before i had a logic analyser. (They are quite cheep on ebay).

Bluetooth - Output Stream

I have connected an arduino with my android device and I have set up the connection and obtained Output Stream.
ANDROID PART
String one = "1";
byte[] input = one.getBytes(Charset.forName("UTF-8"));
mConnectedThread.write(input);
ARDUINO PART
How can I process the received byte[] and convert it back to String?
There is a 128byte buffer on the incoming stream. Use
In your loop():
char inByte;
// check for bytes in the buffer
if (Serial.available() > 0) {
// read the available bytes one at a
// time and purge from buffer
inByte = Serial.read();
// print out byte so you can see it on
// the serial monitor
Serial.print(inByte);
}
If the buffer is big enough for your needs then you won't need to worry about coding anything else. You can deal with the incoming bytes in a char array or read the individual chars into a String object.
There is lots of good information here:
http://arduino.cc/en/Reference/string
...on char arrays and a link at the top of that page to the String object. Let me know if you have further questions, hopefully this gets you at least started and debugging the incoming code correctly

android - Bluetooth: program stuck at inputstream reading

Helo.
Im developing an application that transferes data over bluetooth(with a flight recorder device). When i am recieving a lot of data data(3000 - 40000 lines of text, depends of the file size) my aplication seems to stop recieving the data. I recieve the data with InputStream.read(buffer). For example: I send a command to the flight recorder, it starts sending me a file(line by line), on my phone i recieve 120 lines and then the app stucks.
Intresting is that on my HTC Desire the app stucks just sometimes, on the Samsung Galaxy S phone the application stucks every single time i try to recive more than 50 lines.
The code is based on the BluetoothChat example. This is the part of code where i am listening to the BluetoothSocket:
byte[] buffer = new byte[1024];
int bytes =0;
while(true)
{
bytes = mmInStream.read(buffer);
readMessage = new String(buffer, 0, bytes);
Log.e("read", readMessage);
String read2 = readMessage;
//searching for the end of line to count the lines(the star means the start of the checksum)
int currentHits = read2.replaceAll("[^*]","").length();
nmbrOfTransferedFligts += currentHits;
.
.
.
//parsing and saving the recieved data
I must say that i am running this in a while(true) loop, in a Thread, that is implemented in an android Service. The app seems to stuck at "bytes = mmInStream.read(buffer);"
I have tried to do this with BufferedReader, but with no success.
Thanks.
The app seems to stuck at "bytes = mmInStream.read(buffer);"
But that is normal behavior: InputStream.read(byte[]) blocks when there is no more data available.
This suggests to me that the problem is on the other end or in the communication between the devices. Is is possible that you have a communication problem (which is a bit different on the Galaxy vs. the Desire) that is preventing more data from being received?
Also, I would suggest that you wrap a try/catch around the read statement to be sure that you catch any possible IOException's. Though I guess you would have seen it in logcat if that were happening.
Speaking of logcat, I would suggest that you look at the logcat statements that Android itself it generating. I find that it generates a lot for Bluetooth and this might help you to figure out whether there really is any more data to be read().

Categories

Resources