recieving Frame of 8 bytes in QT Creator GUI via serial port - c++

I'm working to send frame of 8 bytes to Micro-controller Xmega128a1 (via RS232) the frame looks like this
{header1,header2,CMD,D1,D2,D3,D4,CRC},
for example
{0x55,0xaa,0xFF,0x59,0xfd,0x64,0x68,0x32},
Micro-controller has to resend the frame back to PC, if it's 'correct'.
I built GUI in QT Creator I defined the Headers (header0=0x55, header1=0xaa) and CMD=01 also calculated the CRC,
the user has to enter the data field in the Line_Edit which is value in RPM(Real value) The Micro-controller Receive the frame byte byte and resend the full frame, so I have to send the frame in the form of bytes, when I send the frame I receive the headers, command and CRC correctly, but data field Received not in proper way such in the picture below, my problem is with converting the input value in the Line_Edit to bytes to be send inside the frame, when I tried to send the value 1265 RPM I received the frame {55aa0100209e44fb} but I want to receive the frame look like this {55aa014F109e44fb}, where: (1265)DC=(4F1)HEX, I couldn't figure what's the problem with my code:
the way I read data from serial port:
void MainWindow::read()
{
uint64_t size = serial->bytesAvailable();
if (size > 0)
{
QByteArray data;
data.append(serial->readAll());
ui->termial_textEdit->append(data.toHex());
}
}
the send value in RPM code:
#define CMD_SPEED_REF2 0x01
void MainWindow::on_speed_ref2_lineEdit_returnPressed()
{
uint8_t frame2[8];
frame2[0] = 0x55;
frame2[1] = 0xAA;
frame2[2] = CMD_SPEED_REF2;
float fdata2 = 0.0f;
fdata2 = ui->speed_ref2_lineEdit->text().toFloat();
uint8_t *data2 = new uint8_t();
data2 = (uint8_t*)&fdata2;
frame2[3] = data2[0];
frame2[4] = data2[1];
frame2[5] = data2[2];
frame2[6] = data2[3];
frame2[7] = frame2[2] ^ frame2[3] ^ frame2[4] ^ frame2[5] ^ frame2[6];
serial->write((char*)frame2, 8);
}
this Image Illustrate what happens:recived frame

I think your code mostly looks ok. The one area that looks very suspect is your conversion of the text/string back into binary.
Since you convert your binary into a string with:
ui->termial_textEdit->append(data.toHex());
You should in theory be able to use the following to convert it back:
// Convert back...
QByteArray binaryData = QByteArray::fromHex(ui->speed_ref2_lineEdit->text().toLatin1());
// Print to debug to check it...
qDebug("d1: %02x, d2: %02x...etc...\n", binaryData[0], binaryData[1]);
// or just
qDebug() << "data:" << binaryData.toHex() << endl;
Not on my qt PC until Monday so I can't verify this code, so there may be a bug in there somewhere... I'll check it on Monday!
For serial comms I always use QByteArray's instead of char/uint8_t arrays (when using Qt) because they are so easy to use. You can re-build your array like this:
QByteArray frame2;
frame2.append((char) 0x55); // not sure you need to cast it here
frame2.append((char) 0xAA);
frame2.append((char) CMD_SPEED_REF2);
:
etc
:
If you MUST send as a char * then just do:
serial->write(frame2.data(), 8);
//or
serial->write(frame2.data(), frame2.size()); // if you want to send the whole thing

Related

Problem with esp8266 sending large JSON Document via MQTT

I developed a little application that read data from a sensor, store them in SPIFFS memory of my wemos D1 mini (esp8266) and then create a JSON Document and send it via MQTT to my topic. The problem is that as long as I send a JSON Doc with 10 object everything works great, but when I increase the size of the doc over 10 object nothing works. Eventually I need to send a JSON doc with 100 object inside.
What have I already done?
I'm using PubSubClient and I already set the MAX_PACKET_SIZE to the correct value
Using arduinojson assistant I found out the size of my JSON Document (8192 bytes)
I tried to use mqtt.fx to test if the problem was the esp8266 or the mqtt broker. Using mqtt.fx I'm able to send a JSON doc with 100 objects
As soon as I increase the size of the JSON doc I get a wdt error from the serial monitor of my arduino IDE.
I search the internet for wdt error but I don't get what they are and how to solve my problem
Last things I already tried to show on the serial monitor the file.txt in the SPIFFS where I store the data and I can store and then read the 100 object
So in the end I think it's an esp8266 problem and not PubSubClient or MQTT. Am I right?
Does anyone of you here ever encountered this problem before or have some other test I can run?
I search the internet for wdt error but I don't get what they are and how to solve my problem
WDT stands for a Watch Dog Timer. https://os.mbed.com/cookbook/WatchDog-Timer#:~:text=A%20watchdog%20timer%20(WDT)%20is,a%20software%20or%20hardware%20fault.
A watchdog timer (WDT) is a hardware timer that automatically generates a system reset if the main program neglects to periodically service it. It is often used to automatically reset an embedded device that hangs because of a software or hardware fault. Some systems may also refer to it as a computer operating properly (COP) timer. Many microcontrollers including the mbed processor have watchdog timer hardware.
Let's paint a better picture with an example. Let's say that you setup a WDT with a time of 10 seconds. Then the WDT starts counting down from 10 seconds. If it reaches 0 the processor will reset. "Feeding" the WDT will reset the countdown to the original value in this case 10 seconds. So if the WDT has counted down to 4 seconds remaining and you feed it, it resets the countdown back to 10 and starts counting down again.
Does anyone of you here ever encountered this problem before or have some other test I can run?
It looks to me like sending a larger JSON object takes a longer period of time than what the WDT is set for. One possibility would be to break up the JSON object into multiple pieces and send it in smaller chunks instead of one large one. This way the time between WDT "feedings" is reduced. I have no idea if this would be possible for you to change. But this should at least give you a better idea of what's happening.
OK in the end the problem was that sending a large JsonDocument triggered the WDT and the only way I found to overcome this problem was, as suggested by adamvz, to create a main file with all the 100 object, then call a function to split that file in 10 smaller one and send each of them over the internet through an HTTP request or Mosquitto.
Supposing you already created the main file in the spiffs memory, then:
This to split the main file:
void WritePacks() {
sourceFile = LittleFS.open("/file.txt", "r");
if (!sourceFile) {
Serial.println(F("Error: file.txt open failed"));
} else {
Serial.println("File open w/ success");
for (byte idx = 0; idx < outputCount; idx++) {
String aLine;
aLine.reserve(capacity);
if (sourceFile.available() == 0) break;
destinationFile = LittleFS.open(outputFileNames[idx], "w");
if (!destinationFile) {
Serial.print(F("can't open destination "));
Serial.println(outputFileNames[idx]);
break;
} else {
int lineCount = 0;
while (sourceFile.available() && (lineCount <= 10)) {
aLine = sourceFile.readStringUntil('\n');
destinationFile.println(aLine); // double check if the '\n' is in the String or not (--> print or println accordingly)
lineCount++;
}
outputIndex = idx;
Serial.println(outputIndex);
destinationFile.close();
}
} // end for
sourceFile.close();
}
}//end WritePacks
This to publish:
//------ HTTP Publish ------
void httpPublish(){
const char * outputFileNames[] = {"/out1.txt", "/out2.txt", "/out3.txt", "/out4.txt", "/out5.txt", "/out6.txt", "/out7.txt", "/out8.txt", "/out9.txt", "/out10.txt"};
const byte outputCount = sizeof outputFileNames / sizeof outputFileNames[0];
byte outputIndex = 0;
File sourceFile;
File destinationFile;
//Serial.println(capacity);
for (byte idx = 0; idx < outputCount; idx++) {
DynamicJsonDocument doc(capacity);
DynamicJsonDocument globalDoc(capacity);
StaticJsonDocument <1024> localDoc;
String aLine;
aLine.reserve(capacity);
destinationFile = LittleFS.open(outputFileNames[idx], "r");
if (!destinationFile) {
Serial.print(F("can't open destination "));
Serial.println(outputFileNames[idx]);
break;
} else {
Serial.print("Reading: ");
Serial.println(outputFileNames[idx]);
//int lineCount = 0;
while (destinationFile.available()) {
aLine = destinationFile.readStringUntil('\n');
DeserializationError error = deserializeJson(localDoc, aLine);
if (!error) globalDoc.add(localDoc);
else{ Serial.println("Error Writing All files");}
}//while
JsonObject Info = doc.createNestedObject("Info");
Info["Battery"] = battery;
Info["ID"] = id;
Info["Latitudine"] = latitudine;
Info["Longitudine"] = longitudine;
JsonArray Data = doc.createNestedArray("Data");
Data.add(globalDoc);
HTTPClient http;
//Send request
http.begin("yourURL");
char buffer[capacity];
size_t n = serializeJson(doc, buffer);
http.POST(buffer);
Serial.println(buffer);
http.end();
destinationFile.close();
}
}// end for
}//end httpPublish

Sending hex data via serial communication with QT

I am finding way to send hex data via serial communication
i searched it several times and followed some ways but it didn't work.
i checked that protocol is working with using other software that sending hex data to device
below is my code
const char data[]={0xAA,0xAA,0x01,0x00,0x00,0x0E,0x00,0x01,0x00,0x00,0x00,0x2D,0x37,0x1D,0xAA,0xAA,0x01,0x00,0x00,0x0E,0x00,0x0C,0x10,0x00,0x00,0x01,0x76,0x13};
serial->setPortName(("COM8"));
initSerialPort(); // baud rate and etc
if(serial->open(QIODevice::ReadWrite))
{
qDebug()<<"Port is open!";
if(serial->isWritable())
{
qDebug()<<"Yes, i can write to port!";
int size = sizeof(data);
serial->write(data,size);
}
}
and when i use other declare like uint16_t, uchar, write function cannot convert argument 1 from uint16_t (or uchar) to const char *
i did try also this form
QByteArray hex("AAAA0100000E00010000002D371DAAAA0100000E000C100000017613");
QByteArray data = QByteArray::fromHex(hex);
and it also didnt work
You can do this using only QByteArray like:
connect(serial, &QSerialPort::readyRead, this, &YourClass::doSomeStuff);
QByteArray arr;
arr += static_cast<char>(0xAA);
arr += static_cast<char>(0x01);
<...>
serial->setPortName("COM8");
initSerialPort(); // baud rate and etc
if(serial->open(QIODevice::ReadWrite) && serial->isWritable())
serial->write(arr);

Transmitting data from GPS to SIGFOX

I'm working on an Arduino board (microprocessor: ATMega328P) for a University project. I'd like to build a GPS tracker which receives data, stores it, and retransmit it via SIGFOX module.
Basically, I'm able to receive data, and I'm able to send simple SIGFOX commands via serial.
#include <TinyGPS++.h>
#include <String.h>
#include <SoftwareSerial.h>
static const int RXPin = 4, TXPin = 3;
static const uint32_t GPSBaud = 4800;
TinyGPSPlus gps;
SoftwareSerial ss(RXPin, TXPin);
void setup()
{
Serial.begin(115200);
ss.begin(GPSBaud);
Serial.println(F("DeviceExample.ino"));
Serial.println(TinyGPSPlus::libraryVersion());
Serial.println();
}
void loop()
{
// This sketch displays information every time a new sentence is correctly encoded.
while (ss.available() > 0)
if (gps.encode(ss.read())) {
Serial.print(gps.location.lat(), 6); // 4 bytes
Serial.print(F(",")); // 1 byte
Serial.print(gps.location.lng(), 6); // 4 bytes
Serial.print('\n');
delay(4000);
}
if (millis() > 5000 && gps.charsProcessed() < 10){
Serial.println(F("No GPS detected: check wiring."));
while (true);
}
}
This prints correctly on screen the two values (latitude and longitude) that I need to store.
This is the part of the code in TinyGPS++.cpp :
double TinyGPSLocation::lat()
{
updated = false;
double ret = rawLatData.deg + rawLatData.billionths / 1000000000.0;
return rawLatData.negative ? -ret : ret;
}
double TinyGPSLocation::lng()
{
updated = false;
double ret = rawLngData.deg + rawLngData.billionths / 1000000000.0;
return rawLngData.negative ? -ret : ret;
}
Now I'd like to store this data and send it through the SIGFOX module.
A SIGFOX command is:
'N X'
Where N represents the number of bytes that are to be transmitted, and X are the values of the bytes. For example: '1 255' is 1 byte with value 255, and returns FF as output.
The problem is that the values are doubles so I don't know how to write them in the SIGFOX command.
Another problem is that I don't know how to create two serial communications in the code. I tried it but it doesn't seem to work.
Thank you so much in advance.
I saw some of the API info on the SIGFOX, I'm assuming it is this. Even if it isn't it's probably close enough for the point I'm trying to make.
https://support.sigfox.com/apidocs#operation/getDevice
You need to understand to some extent what IEEE 754 is as in my experience this is how equipment passes the data back and forth if you look at the raw bit stream.
https://en.wikipedia.org/wiki/IEEE_754
So, it is a double you send over 8 bytes on most platforms and 4 bytes for a float. When you print to the screen of hover over a variable in debug mode, the IDE/compiler takes care of this for you and gives you number with decimal points.
For making another serial port, you need to make another variable and pass in the baud rate etc of that device.

Determine Data Type on a TCP Socket in Qt

I am writing a program to send images captured from an OpenCV window over a TCP connection, using Qt libraries to setup the connections etc.
I have to functions (below) which are both working to send either text or a byte array. The problem I have is at the other end how can I tell if the data coming in is plain text, or an array containing an image. Is there an inbuilt way to do this, or do I need to put a byte at the start of the data to tell the receiver what data is coming? I already put the array length at the start of the serialized image data.
void Screenshot_controller::sendText(std::string textToSend)
{
if(connectionMade)
{
std::string endLine = "\r\n";
textToSend = textToSend + endLine;
const char * textChar = textToSend.c_str();
sendSocket->write(textChar);
sendSocket->flush();
qDebug() << "Text Sent from Server";
}
}
void Screenshot_controller::sendData(QByteArray dataToSend)
{
if(connectionMade)
{
sendSocket->write(dataToSend);
sendSocket->flush();
qDebug() << "Data Sent from Server";
}
}
You need to define the protocol yourself, whether that's with a byte, string, JSON header or any other method. The Tcp socket will allow you to transfer the data, but doesn't care what that data is; it's up to you to handle that.

Android MediaPlayer / Stagefright crashes reading SDP from RTSP server

I am trying to use Android's MediaPlayer class to play an RTSP stream. MediaPlayer calls to a native library called stagefright to make this happen. This library, and the entire media framework, crash on the following error:
15988-23172/? A/APacketSource﹕ frameworks/av/media/libstagefright/rtsp/APacketSource.cpp:143 CHECK_EQ( (unsigned)nalType,7u) failed: 22 vs. 7
So it seems pretty obvious what the error is - the assert fails when nalType is supposed to be 7, but instead evaluates to 22. I don't understand why this is though. For context, the RTSP stream's SDP contains an attribute sprop-parameter-sets, which is a base64-encoded set of bytes. nalType seems to refer to the first byte of the result of base64-decoding sprop-parameter-sets. In this instance, this is the base64-encoded version:
NjdkMDAxNmRhMDI4MGY2YzA1NTIwMDAwMDAzMDA0MDAwMDAwNzhjMDgwMDNlODAwMDBhOGMzN2JkZjBiYzIy
Decoded, it should look like this:
67d0016da0280f6c0552000000300400000078c08003e80000a8c37bdf0bc22
Below is the relevant excerpt from APacketSource.cpp, from the Android 4.4 source code:
// Appears to assign value of "sprop-parameter-sets" from SDP to 'val'
if (!GetAttribute(params, "sprop-parameter-sets", &val)) {
return NULL;
}
size_t start = 0;
for (;;) {
ssize_t commaPos = val.find(",", start);
size_t end = (commaPos < 0) ? val.size() : commaPos;
AString nalString(val, start, end - start);
sp<ABuffer> nal = decodeBase64(nalString);
CHECK(nal != NULL);
CHECK_GT(nal->size(), 0u);
CHECK_LE(nal->size(), 65535u);
// Mask away everything but 0001 1111 from the first byte
uint8_t nalType = nal->data()[0] & 0x1f;
if (numSeqParameterSets == 0) {
// Line 143, where the failure happens.
CHECK_EQ((unsigned)nalType, 7u);
}
...
}
The first byte, 0x67, after being masked, should evaluate to 0x07. Somehow, it valuates to 0x16. I have no idea why this may be, though I suspect maybe something unusual is being returned by nal->data().
I can provide the stacktrace that gets printed to the log, but it's quite large and I'm not sure it's relevant. Why is this assert failing?