How to prevent bluetooth from sending concatenated data - multithreading

In advance, I want to say sorry for my poor english.
I'm working on a project which uses cellphone's bluetooth to send two bytes of data to a MCU through HC-05 bluetooth module each time. Since the MCU has no buffer to store the received data, I have to send one byte twice with interval at least 10ms.
I use an oscilloscope to monitor the HC-05 module. In most of time, my phone sends two packets with one byte of data in each, but sometimes it sends two packet together and therefore the MCU cannot handle it.
below is how I define the sending method
public void sendData(){
Byte byte_send = (byte) Integer.parseInt(tmp_addr);
byte[] tmp = new byte[]{byte_send};
Byte byte_2 = (byte) Integer.parseInt(tmp_data);
byte[] temp = new byte[]{byte_2};
try {
mOutStream.write(tmp);
mOutStream.flush();
this.sleep(20);
mOutStream.write(temp);
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Can anyone tell me why causes that to happen? Is it because "sleep(20);" didn't work or something else?

I assume the flush only means write the data from outputstream to Bluetooth stack does not mean write the data to remote device? sorry I was not check the code yet.
However for synchronize purpose, can your remote device echo the received data back then your app can send the second byte to remote?

Related

Crackly audio when sending audio via bluetooth->arduino->DAC->3.5mm breakout board->headphones. Do not know the cause

I wrote a mix of python code and arduino code to make this work. I am sending an array of numbers (audio) to the HC-05 bluetooth module/arduino uno (these are both set to communicate via serial at 115200 baud, at least that is what I set for both (Serial.begin(x) for arduino and through AT commands for HC-05) ranging from 0-4095 as strings from python via bluetooth (bluetoothsocket(RFCOMM)).They are received character by character in the arduino and read into an array which will convert the char array into the single original unsigned int. Up to there I can confirm that chars were received and definitely constructed into integers. Those integer values are passed into a 12-bit DAC via I2C (SDA (A4)/SLC (A5) pins on the arduino. On the webpage (https://learn.adafruit.com/mcp4725-12-bit-dac-tutorial/using-with-arduino) it says that to increase the speed for the transmission you write this "TWBR = 12; // 400 khz" in the arduino script, I'm guessing. Otherwise the DAC will transmit at 100kHz; so I set the transmission speed to 400kHz for the DAC. When I connect the DAC output to the 3.5mm breakout/earbuds I only hear crackling, absolutely no "sound". The earbuds work just fine on my laptop, so the problem is something else. The DAC definitely outputs a voltage (triangle wave file from webpage works) and I tried two 3.5mm breakout boards (maybe shoddy soldering work?). Does anyone have an idea of what the issue could be or steps I could take to find what the error is? My guess is that somewhere the transmission rates/bit transfers do not line up, but that is what I'm trying to find out by asking.
On the python side, the code more or less looks like this:
*initializing socket, setting to non-blocking socket,etc..
for i in range((1000)): #just to test, the file Id like to send is maybe 300,000 strings
HC05_socket.send(soundchars[i])
And this is the arduino code:
#define ledPinr 4
#include <Wire.h>
#include <Adafruit_MCP4725.h>
Adafruit_MCP4725 dac;
int wait =10000; //
void setup() {
// put your setup code here, to run once:
pinMode(ledPinr, OUTPUT);
digitalWrite(ledPinr, LOW);
Serial.begin(115200);
dac.begin(0x62);
TWBR = 12; // 400 khz done in library
Serial.setTimeout(wait); // for now
}
void loop() {
// Read serial input:
char val[4]; // length 4 for 12-bit resolution
if (Serial.available()){
digitalWrite(ledPinr, LOW);
Serial.readBytesUntil(',', val, 4);
int num = atol(val);
dac.setVoltage(num, false);
Serial.print(num);
}
if (Serial.available()==0){
digitalWrite(ledPinr, HIGH);
}
}
Note: ignore the LED code lines, that is just to have an idea of the data flow as I run the program.
There are many reasons that can lead to crackling audio especially in these kind of setups (as I'm sure you're aware).
A couple of things :
Although in the example you link it says to write TWBR = 12, if you look at the source code of the library it checks for the #define TWBR macro. So I would change your code to have #define TWBR 12 before your setup() function.
How often are you receiving the bluetooth data? It doesn't look like you are handling what's happening when you receive no data the DAC will just freeze on whatever value you wrote last
Make sure you are calling the right address -> you didn't mention if A0 is connected to VCC in your setup.
First, be sure to call begin(addr) where addr is the i2c address
(default is 0x62, if A0 is connected to VCC its 0x63)
Side notes:
In my experience people try to avoid using atol(). If you look at adafruit's examples they use pgm_read_word() instead.
12 Bit isn't very high audio resolution for audio playback so most audio will be distorted (other than very basic digital sounds)
Make sure the audio you're sending from Python is playable (I don't know what your test case is)
In the end it could always be the soldering but I think it will be unlikely.

Flushing tx udp socket kernel buffers to reduce latency

I have a Linux based wireless network application which requires to be pretty hard on latency. i.e., late arrival of a data packet is no better at all compared to no data. Also, Old data in the socket can only delay the newer data.
I'm looking if from the transmit side there is any way to detect that the socket is piling up with old data and in such case flush/discard it and send fresh data.
I know the receiver can read all of the old data and discard. However, this will still play catch up and not really help in speeding up as well as if there was a sender side option to evaluate.
Thanks for any help.
Try turning off the Nagle algorithm on the sending side. This algorithm tries to collect smaller packets into larger ones to reduce overhead, so turning it off can mean each packet is sent immediately. Here's a code snippet to turn it off:
void noNagle (int socket)
{
int on = 1;
if (setsockopt (socket, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)) < 0)
bye ("Can not disable nagle algorithm\n");
}

Characters not properly displayed in serial monitor in arduino

Can anyone tell me why the characters are not getting printed properly in the serial monitor of Arduino? I am pasting the arduino code.
#include <SoftwareSerial.h>
#include <LiquidCrystal.h>
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12,11,5,4,3,2);
int bluetoothTx = 15;
int bluetoothRx = 14;
SoftwareSerial bluetooth(bluetoothTx, bluetoothRx);
int incomingByte;
void setup() {
pinMode(53, OUTPUT);
Serial.begin(9600);
lcd.begin(16, 2);
lcd.clear();
bluetooth.begin(115200); // The Bluetooth Mate defaults to 115200bps
delay(320); // IMPORTANT DELAY! (Minimum ~276ms)
bluetooth.print("$$$"); // Enter command mode
delay(15); // IMPORTANT DELAY! (Minimum ~10ms)
bluetooth.println("U,9600,N"); // Temporarily Change the baudrate to 9600, no parity
bluetooth.begin(9600); // Start bluetooth serial at 9600
lcd.print("done setup");
}
void loop()
{
lcd.clear();
Serial.print("in loop");
//Read from bluetooth and write to usb serial
if(bluetooth.available()) {
Serial.print("BT here");
char toSend = (char)bluetooth.read();
Serial.print(toSend);
lcd.print(toSend);
delay(3000);
}delay(3000);
}
Can anyone take a look into it. It does not print the character that I provide instead it prints something else like 'y' with 2 dots on top etc. Tried almost all the available solution.
Your issues could be one of a couple things. First and easiest to check is COMMON GROUND. Did you connect just the RX and TX pins or also the GND (ground) pin? Make sure that the ground from the BT mate is connected to the Arduino ground.
If you have done that, then your issue is with the baud rate. I'm pretty sure that SoftwareSerial can't read at baud rates beyond 57600. Arduino.cc docs say it can read at 115200, but other places say it will only write up to 115200.
To test this, you will either need to change the settings for this on the Bluetooth Mate or use a Mega or Leonardo which will have a hardware serial port (other than the one used for USB) which you should be able to configure for 115200.
If you try it with hardware serial either on a Mega or just using an FTDI or something and the messages still look garbled then perhaps the bluetooth mate is not actually configured to talk at 115200 as it claims. Trying reading the docs or testing with other baud rates.
Check whether error is present due to one of the following reasons:-
1) You haven't given any command to exit from the data mode. After setting the baudrate to 9600, you are directly switching to loop. You haven't given the command to exit the command mode.
2) I too had the same problem when I was using RN171 Wi-Fi module. The cause of the problem in my case was because I was sending data to Wi-Fi module in integer format instead of uint_8. While reading from the Wi-Fi module serially with arduino mega, I was reading it in the format of characters.
You have to remember that int is actually signed 16 bit integer. So while sending data to your Bluetooth module you have to send it as uint_8 or ASCII values of the characters that you want to send. You should also read it in the same format as you sent it.
3) If these are not the error then as calumb said, there can be error in setting the bluetooth module in command mode. You haven't checked for reply from bluetooth module whether it is really in command mode or not. You must read an CMD reply from bluetooth module and at the end of every command a reply of ack to conform that its really done what you want it to do.
This may be because of Bluetooth parsing data simultaneously. when sending two different data at the same time this may happens. try to control your data flow.

force socket disconnect without forging RST, Linux

I have a network client which is stuck in recvfrom a server not under my control which, after 24+ hours, is probably never going to respond. The program has processed a great deal of data, so I don't want to kill it; I want it to abandon the current connection and proceed. (It will do so correctly if recvfrom returns EOF or -1.) I have already tried several different programs that purport to be able to disconnect stale TCP channels by forging RSTs (tcpkill, cutter, killcx); none had any effect, the program remained stuck in recvfrom. I have also tried taking the network interface down; again, no effect.
It seems to me that there really should be a way to force a disconnect at the socket-API level without forging network packets. I do not mind horrible hacks, up to and including poking kernel data structures by hand; this is a disaster-recovery situation. Any suggestions?
(For clarity, the TCP channel at issue here is in ESTABLISHED state according to lsof.)
I do not mind horrible hacks
That's all you have to say. I am guessing the tools you tried didn't work because they sniff traffic to get an acceptable ACK number to kill the connection. Without traffic flowing they have no way to get hold of it.
Here are things you can try:
Probe all the sequence numbers
Where those tools failed you can still do it. Make a simple python script and with scapy, for each sequence number send a RST segment with the correct 4-tuple (ports and addresses). There's at most 4 billion (actually fewer assuming a decent window - you can find out the window for free using ss -i).
Make a kernel module to get hold of the socket
Make a kernel module getting a list of TCP sockets: look for sk_nulls_for_each(sk, node, &tcp_hashinfo.ehash[i].chain)
Identify your victim sk
At this point you intimately have access to your socket. So
You can call tcp_reset or tcp_disconnect on it. You won't be able to call tcp_reset directly (since it doesn't have EXPORT_SYMBOL) but you should be able to mimic it: most of the functions it calls are exported
Or you can get the expected ACK number from tcp_sk(sk) and directly forge a RST packet with scapy
Here is function I use to print established sockets - I scrounged bits and pieces from the kernel to make it some time ago:
#include <net/inet_hashtables.h>
#define NIPQUAD(addr) \
((unsigned char *)&addr)[0], \
((unsigned char *)&addr)[1], \
((unsigned char *)&addr)[2], \
((unsigned char *)&addr)[3]
#define NIPQUAD_FMT "%u.%u.%u.%u"
extern struct inet_hashinfo tcp_hashinfo;
/* Decides whether a bucket has any sockets in it. */
static inline bool empty_bucket(int i)
{
return hlist_nulls_empty(&tcp_hashinfo.ehash[i].chain);
}
void print_tcp_socks(void)
{
int i = 0;
struct inet_sock *inet;
/* Walk hash array and lock each if not empty. */
printk("Established ---\n");
for (i = 0; i <= tcp_hashinfo.ehash_mask; i++) {
struct sock *sk;
struct hlist_nulls_node *node;
spinlock_t *lock = inet_ehash_lockp(&tcp_hashinfo, i);
/* Lockless fast path for the common case of empty buckets */
if (empty_bucket(i))
continue;
spin_lock_bh(lock);
sk_nulls_for_each(sk, node, &tcp_hashinfo.ehash[i].chain) {
if (sk->sk_family != PF_INET)
continue;
inet = inet_sk(sk);
printk(NIPQUAD_FMT":%hu ---> " NIPQUAD_FMT
":%hu\n", NIPQUAD(inet->inet_saddr),
ntohs(inet->inet_sport), NIPQUAD(inet->inet_daddr),
ntohs(inet->inet_dport));
}
spin_unlock_bh(lock);
}
}
You should be able to pop this into a simple "Hello World" module and after insmoding it, in dmesg you will see sockets (much like ss or netstat).
I understand that what you want to do it's to automatize the process to make a test. But if you just want to check the correct handling of the recvfrom error, you could attach with the GDB and close the fd with close() call.
Here you could see an example.
Another option is to use scapy for crafting propper RST packets (which is not in your list). This is the way I tested the connections RST in a bridged system (IMHO is the best option), you could also implement a graceful shutdown.
Here an example of the scapy script.

How can I digitalRead a pin and convert data to String on Arduino?

I'm doing a communication system with 2 Arduinos Leonardo. To transmit I had to convert a String in bits and send them through a PWM pin. The question is, how can I do the receiver?
My idea is to receive data in a digital pin, so I can convert LOW/HIGH to '0' and '1', put 8 bits in a string, convert to char and then I have my final String.
Some info:
- I'm using PWM because I want to implement FSK modulation, sending bit by bit;-
- I have some hardware to get communication system working;
- My physical channel for communication is Serial (via Arduino pins);
- In the receiver hardware will provide me TTL signals, so I will have 0V/5V. That's why I think digitalRead() should work;
- Data is sent via PWM and received in two level signals;
- I'll have to do some protocol to send/receive data, but still don't know how...
This is the code I wrote:
void setup() {
Serial.begin(9600);
while (!Serial) {;}
}
void loop() {
char bitPosition = 0;
String inMessage = 0;
while (Serial.available() > 0) {
char outChar;
boolean digValue = digitalRead(inPin);
for(bitPosition = 7; bitPosition >= 0; ){
if(digValue == LOW){
bitWrite(outChar, bitPosition, 0);
}
if(digValue == HIGH){
bitWrite(outChar, bitPosition, 1);
}
bitPosition--;
}
inMessage.concat(outChar);
if(inMessage != 0){
Serial.println("Received: " + inMessage);
}
}
}
I want this code to transform HIGH/LOW states from digitalRead in a string of characters. 0/1 -> char (outChar) -> String (inMessage). I don't know if i'm not thinking right. Suggestions?
Should I have to do something about baudrate to receive/transmit data? How?
Any help/suggestion would be appreciated.
Look at how SoftwareSerial is implemented in Arduino for a clue as to how to get this done.
http://arduino.cc/en/Reference/SoftwareSerial
"The SoftwareSerial library has been developed to allow serial communication on other digital pins of the Arduino, using software to replicate the functionality (hence the name "SoftwareSerial")."
Well, your problem if far more complicated that you believe. I have read your similar (identical?) question posted on EE.SE.
It seams that you haven't catch a fundamental thing about your issue.
It is not a software problem. If I summarize your issue, globally.
You want to send data from arduino A to arduino B.
You plan to generate a FSK signal using a PWM pin of arduino A.
first comment: How ? Look-up table of a sine wave where the pointer moves according to the phase modulation? This seems easy. So let's believe this it the way you choose.
(here you say it is a logic signal, but on EE.SE you say it's a wireless signal)
Now you have a signal at XX kHz (we don't know the XX value. But accordint to the Xtal speed of your Arduino, I can't be much greater than ~500Khz)
On arduino B, you have to solve the problem of clock recovery because on arduino B you don't have access to the clock of arduino A. This means that you can't compare the signal you are getting with a reference clock. When you analyse the received signal you get a certain phase relative to your local clock. But because you cannot know the reference phase of ardunio A, you cannot say if the receive bit is -90° or +90°. Thus you can't assign a 0 or 1 to the received signal.
This is not a trivial problem. According to your answer to the question and comments here or on EE.SE, you are trying to solve implementation problem of an algorithm that is probably not working. Your should first try to find a suited algorithm that you may simulate using MATLAB (or the free OCTAVE), make sure it is working, and next try to implement it on embedded hardware.
You receive a lot of answer on EE.SE about what do you want to do. It's because it makes no sens to solve an issue about implementing something that looks false to an expert.
Thus, if you want meaningful answers. Please spend more time explaining us what and how, conceptually, you plan to solve your problem.
Add information about how your think your FSK works. How do you plan to use PWM to do FSK, this in not trivial. And how you plan, conceptually to detect that a received symbol is a 1 or a 0.
As it is, my answer is : Event if we can solve you copy bit issue, it won't solve your problem.

Resources