This question already has an answer here:
QSerialPort - wating for whole data from sender
(1 answer)
Closed 3 years ago.
I use QSerialPort to receive data from serial port of computer. It works well. However, when my device sends 00aabbcc, the readReady() signal is called even when only 00 or 00aa is received.
How can I get a signal, only when all 00aabbcc is received?
Here my code in slot:
QByteArray data = mySerial->readAll();
QString DataAsString = data.toHex();
ui->logArea->append(DataAsString);
What I see in the textEdit logArea is:
00
aabb
cc
00aabb
cc
What i need is
00aabbcc
00aabbcc
readReady() fires as soon as you get something in the buffer. If you want to read a fixed number of bytes you need to check for the packet size yourself.
This solution should work for you.
Related
Currently I implement code bluetooth low engine (BLE) for STM32L476 + X-NUCLEO-IDB04A1 base on example "sensor demo".
In "Sensor Demo" example, it only code to send data to smart phone. And don't have receive data.
I think can use function below to read data:
tBleStatus aci_gatt_read_charac_val(uint16_t conn_handle, uint16_t attr_handle)
And can read data from HCI_Event_CB(hciReadPacket->dataBuff);
However I don't know how to get parameter "uint16_t attr_handle" for function
tBleStatus aci_gatt_read_charac_val(uint16_t conn_handle, uint16_t attr_handle)
Could you explain for me about this problem?
That would be the value of the handle for this connection.
When IDB04A1 successfully connects to the smart phone, it shall send a HCI_LE_META_EVENT with information for this connection. Connection_Handle can be found in the event, to be specific, a 16-byte value:
(offset 6 | offset 5)
I am currently working on a simple serial interface on a UNIX based device and cant find a definitive answer to the following:
I am currently trying to determine if a 'pure time read' (VMIN = 0, VTIME >0) will return half way through reading to n_bytes, as the timer is started when read is called, not when the first character is received.
For example, if I send a message to the device on the other end of the serial interface and I want a response I'd attempt the following (pseudo code):
m_tty.c_cc[VMIN] = 0;
m_tty.c_cc[VTIME] = 5; //i.e. > 0
write(myFileHandle, myData, sizeof(myData));
usleep(sizeof(myData) * 100); //assuming 100 us per char to Tx.
read(myFileHandle, myRxData, expectedMinNumBytes);
I am unclear as to whether read() would return if the first byte arrived just as the timer was about to expire, or if it would continue until 'expectedMinNumBytes' once the first is received?
Thanks for the help in advance!
This is a pure timed read. If there is available data, the read is immediately satisfied. If there is no data, the timer is started at the time read is called, and the read returns: either because the timer expires (returns 0) or a single byte is available.
I am having hell with this and I know it is probably really simple. I am trying to read a text message from my Seeed GPRS shield. I have the shield setup as a software serial and I am displaying the information received from the GPRS to the serial monitor. I am currently sending all AT commands over serial while I work on my code. To display the data from the software serial to the serial monitor, I am using the following code.
while(GPRS.available()!=0) {
Serial.write(GPRS.read());
}
GPRS is my software serial obviously. The problem is, the text is long and I only get a few characters from it. Something like this.
+CMGR: "REC READ","1511","","13/12/09,14:34:54-24" Welcome to TM eos8
This text is a "Welcome to T-Mobile" text that is much longer. The last few characters shown are scrambled. I have done some research and have seen that I can mod the serial buffer size to 256 instead of the default 64. I want to avoid this because I am sure there is an easier way. Any ideas?
Have you tried reading into a character array, one byte at a time? See if this helps:
if (GPRS.available()) { // GPRS talking ..
while(GPRS.available()) { // As long as it is talking ..
buffer[count++]=GPRS.read();
// read char into array
if(count == 64) break; // Enough said!
}
Serial.write(buffer,count); // Display in Terminal
clearBufferArray();
count = 0;
}
You need to declare the variables 'buffer' and 'count' appropriately and define the function 'clearBufferArray()'
Let me know if this helps.
Looks like this is simply the result of the lack of flow control in all Arduino serial connections. If you cannot pace your GPRS() input byte sequence to a rate that guarantees the input FIFO can't overflow, then your Serial.write() will block when the output FIFO fills. At that point you will be dropping new GPRS input bytes on the floor until Serial output frees up more space.
Since the captured output is apparently clean up to about 64 bytes, this suggests
a) a 64 byte buffer,
b) a GPRS data rate much higher than the Serial one, and
c) that the garbage data is actually the occasional valid byte from later in the sequence.
You might confirm this by testing the return code from Serial.write. If you get back zero, that byte is getting lost.
If you were using 9600 for Serial and 57600 for GPRS, I would expect somewhat more than 64 bytes to come through before the output gets mangled, but if the GPRS rate is more than 64x the Serial rate, the entire output FIFO could fill up within a single output byte transmission time.
Capturing to an intermediate buffer should resolve your issue, as long as it is large enough for the whole message. Similarly, extending the size of either the source (in conjunction with testing the Serial.write) or destination (without any additional code) FIFOs to the maximum datagram size should work.
I've had the same problem trying to read messages and get 64 characters. I overcame it by adding a "delay(10)" in the loop calling the function that does the read from the GPRS. Seems to be enough to overcome the race scenario. - Using Arduino Mega.
void loop() {
ReadmyGPRS();
delay(10); //A race condition exists to get the data.
}
void ReadmyGPRS(){
if (Serial1.available()){ // if data is comming from GPRS serial port
count = 0; // reset counter
while(Serial1.available()) // reading data into char array
{
buffer[count++]=Serial1.read(); // writing data into array
if(count == 160)break;
}
Serial.write(buffer,count);
}
}
I'm following the sparkfun tutorial for connecting an arduino to electric imp. I only have one arduino and imp, so I'm trying to get whatever I type in the arduino serial monitor to display in the imp node using server.show().
I've modified one of the functions in the sparkfun code to look like this:
function pollUart()
{
imp.wakeup(0.00001, pollUart.bindenv(this)); // schedule the next poll in 10us
local byte = hardware.uart57.read(); // read the UART buffer
// This will return -1 if there is no data to be read.
while (byte != -1) // otherwise, we keep reading until there is no data to be read.
{
// server.log(format("%c", byte)); // send the character out to the server log. Optional, great for debugging
// impeeOutput.set(byte); // send the valid character out the impee's outputPort
server.show(byte)
byte = hardware.uart57.read(); // read from the UART buffer again (not sure if it's a valid character yet)
toggleTxLED(); // Toggle the TX LED
}
}
server.show(byte) is only displaying seemingly random numbers. I have an idea of why this is, I just don't know how to fix it because I'm not that familiar with UARTs and squirrel.
local byte = hardware.uart57.read(); reads in the ascii characters from the arduino in byte form (I think), and they're not being 'translated' into their ascii characters before I use server.show(byte).
How do I do this in squirrel?
Also, I think polling every 10us is the wrong way to go here. I'd like to only poll when there's new information, but I also don't know how to do that in squirrel. Can someone point me to an example where this happens?
Thanks!
I think you are passing the wrong data type to the show method of the server object. The electric imp docs state that it takes a string, server.show(string). I think that local is the correct type to receive the value from hardware.uart57.read(). You can tell from the docs as well. So, you need to find a way to cast your byte to a string. I bet you could find the answer here. From what I read Squirrel use's Unicode so there is a probably a function that takes Unicode bytes and loads them into a string object.
I'm having a bit of a problem with the communication to an accelerometer sensor. The sensor puts out about 8000 readings/second continuously. The sensor is plugged in to a usb port with an adaper and shows up as com4. My problem is that I can't seem to pick out the sensor reading packets from the byte stream. The packets have the size of five bytes and have the following format:
High nibble Low nibble
Byte 1 checksum, id for packet start X high
Byte 2 X mid X low
Byte 3 Y high Y mid
Byte 4 Y low Z high
Byte 5 Y mid Y low
X, y, z is the acceleration.
In the documentation for the sensor it states that the high nibble in the first byte is the checksum (calculated Xhigh+Xlow+Yhigh+Ylow+Zhigh+Zlow) but also the identification of the packet start. I'm pretty new to programming against external devices and can't really grasp how the checksum can be used as an identifier for the start of the package (wouldn't the checksum change all the time?). Is this a common way for identifying the start of a packet? Does anyone have any idea how to solve this problem?
Any help would be greatly appreciated.
... can't really grasp how the checksum can be used as an identifier for the start of the package (wouldn't the checksum change all the time?).
Yes, the checksum would change since it is derived from the data.
But even a fixed-value start-of-packet nibble would (by itself) not be sufficient to (initially) identify (or verify) data packets. Since this is binary data (rather than text), the data can take on the same value as any fixed-value start-of-packet. If you had a trivial scan for this start-nibble, that algorithm could easily misidentify a data nibble as the start-nibble.
Is this a common way for identifying the start of a packet?
No, but given the high data rate, it seems to be a scheme to minimize the packet size.
Does anyone have any idea how to solve this problem?
You probably have to initially scan every sequence of bytes five at a time (i.e. the length of a packet).
Calculate the checksum of this "packet", and compare it to the first nibble.
A match indicates that you (may) have packet alignment.
A mismatch means that you should toss the first byte, and test the next possible packet that would start with what was the second byte (i.e. shift the 4 remaining bytes and append a new 5th byte).
Once packet alignment has been achieved (or assumed), you need to continually verify the checksum of every packet in order to confirm data integrity and ensure packet data alignment. Any checksum error should force another hunt for correct packet data alignment (starting at the 2nd byte of the current "packet").
What you need to do is get some free SerialPortTerminal in c# import in your project and first check all the data and packets you are getting, unless you have already done that. Than just to read you will need to do something like...
using System;
using System.IO.Ports;
using System.Windows.Forms;
namespace SPE
{
class SerialPortProgram
{
// Create the serial port with basic settings
private SerialPort port = new SerialPort("COM4", 9600, Parity.None, 8, StopBits.One);
[STAThread]
static void Main(string[] args)
{
// Instatiate this class
new SerialPortProgram();
}
private SerialPortProgram()
{
Console.WriteLine("Incoming Data:");
// Attach a method to be called when there // is data waiting in the port's buffer
port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
// Begin communications
port.Open();
// Enter an application loop to keep this thread alive
Application.Run();
}
private void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
// Show all the incoming data in the port's buffer
Console.WriteLine(port.ReadExisting());
}
}
}