How to read serial data from Qt5 - qt

I am making a Qt5 an application to read data from the ESP32 microcontroller which I am programming with the Arduino framework using PlatformIO.
The problem I'm having is that I can't get the data to be received in uniform numbers of bytes. Sometimes I receive 1 byte, other times 2 bytes. Is this normal or is there a way to receive a complete buffer every time?
Qt Code:
void Dialog::on_connect_clicked()
{
if(esp_available){
esp->setPortName(espPortName);
esp->open(QSerialPort::ReadWrite);
esp->setBaudRate(9600);
esp->setDataBits(QSerialPort::Data8);
esp->setParity(QSerialPort::NoParity);
esp->setStopBits(QSerialPort::OneStop);
esp->setFlowControl(QSerialPort::NoFlowControl);
connect(esp, SIGNAL(readyRead()), this, SLOT(on_startStream_clicked()));
}
void Dialog::on_ledOn_clicked()
{
if(esp->isOpen()){
esp->write("1");
}
}
void Dialog::on_startStream_clicked()
{
QByteArray ba;
if(esp->isOpen()){
ba = esp->readAll();
qDebug() << ba;
}
}
Arduino Code:
#include <Arduino.h>
void setup()
{
Serial.begin(9600);
}
void loop()
{
while (Serial.available() > 0)
{
int val = Serial.read() - '0';
if (val == 1)
{
Serial.write("Hello");
}
}
Serial.flush();
}
Clicking the button 3 times sends the following output:
H
e
ll
o
H
e
l
lo
H
e
l
lo
What I would like to see in the output is either the individual characters, or the entire packet/buffer in one line,
Any suggestions?

It is normal to receive bytes of different sizes, in these cases a simple way to find a delimiter is better. For example in your case it is better to use endline ("\n") as delimiter:
Serial.println("Hello");
// or
// Serial.write("Hello\n");
void Dialog::on_startStream_clicked()
{
QByteArray ba;
while(esp->canReadLine()){
ba = esp->readLine();
qDebug() << ba;
}
}

Related

How to configure watchdog for the arduino Nano 33 BLE Sense board?

For the arduino Nano 33 BLE Sense board, the standard avr/wdt.h is not available. And it seems that no standard library provides it. How to use the watchdog system for this board ? I found no full information about it.
I've found the page https://www.mysensors.org/apidocs/group__avr__watchdog.html which allow to configure the reboot mode. And it works.
But no way to configure the interruption mode with ISR() function.
Moreover, there's no explanation about the manipulation of used register/variables for any fine configuration.
Simple code example with regular asynchronous stuff using the watchdog ISR() mechanism. It which works well with ATmega328 (e.g.UNO). But I do not find equivalent configuration for the Nano 33 BLE using the nRF52840.
# include <avr/wdt.h>
volatile byte led;
int k;
ISR(WDT_vect) {
Serial.println("Asynchronous stuff in ISR() function");
digitalWrite(LED_BUILTIN,led);
led=!led;
}
void setup() {
pinMode(LED_BUILTIN,OUTPUT);
led=0;
Serial.begin(9600);
while(!Serial) {}
Serial.println("== R E B O O T ==");
WDTCSR = ( 1 << WDE ) | ( 1 << WDCE );
WDTCSR = ( 1 << WDP2 ) | ( 1 << WDP0 ) | ( 1 << WDIE ) ; // Interruption and timeout 1/2 s
}
void loop() {
Serial.print("Loop #");
Serial.println(k);
if (k++%2) {
Serial.println("Some stuff (even branch)");
delay(1200);
}
else {
Serial.println("Some stuff (odd branch)");
delay(4800);
}
}
Thks.
In fact, for the RF52940, I'm not sure that the watchdog can provide the needed interruption mechanism despite it exists the INTENSET bit for interruption according to the chipset doc https://content.arduino.cc/assets/Nano_BLE_MCU-nRF52840_PS_v1.1.pdf).
But the good way is for sure the use of timers (and one can use more than just one, quite good).
For a similar behaviour as the code given for the UNO before, here is the code one can write for the Nano BLE using a timer interrupt (see https://github.com/khoih-prog/NRF52_MBED_TimerInterrupt for full and usefull doc).
#include "NRF52_MBED_TimerInterrupt.h"
volatile byte led;
volatile uint32_t count=0;
NRF52_MBED_Timer myTimer(NRF_TIMER_1);
unsigned k=0;
void myHandler() {
digitalWrite(LED_BUILTIN,led);
led=!led;
count++;
}
void setup() {
pinMode(LED_BUILTIN,OUTPUT);
led=0;
Serial.begin(9600);
while(!Serial) {}
Serial.println("== R E B O O T ==");
if (myTimer.attachInterruptInterval(500*1000, myHandler)) // each 1/2 second
Serial.println("myTimer launched");
else
Serial.println("Can not set the timer");
}
void loop() {
Serial.print("Loop #");
Serial.print(k);
Serial.print(" and nb times in Handler : ");
Serial.println(count);
if (k++%2) {
Serial.println("Some stuff (even branch)");
delay(1200);
}
else {
Serial.println("Some stuff (odd branch)");
delay(4800);
}
}

Serial communication between two arduino

I am trying to write a Serial read function. That function will give me a data between '#' (start character) and '*' (end character). I tried to write it and it looks like it is kinda work but not perfectly. The problem is that:
I have two arduino. One of these send "MARCO" and other arduino read it. If the readed data is "MARCO" it is write to serial monitor "MARCOCORRECT" else it is write to serial monitor the readed data. Normally it must just write "MARCOCORRECT" because I only send "MARCO" but it don't. It writes something else too. I tried lower baud rate too but it is still same. How can I fix it?
Sender Code
#define BAUD_RATE 38400
void setup()
{
Serial.begin(BAUD_RATE);
}
String readed = "";
void loop()
{
String readed;
while (Serial.available() > 0)
{
readed += Serial.read();
}
Serial.println("#MARCO*");
}
Reader Code
#define BAUD_RATE 38400
#define MSG_START '#'
#define MSG_END '*'
String readed;
char readedChar;
bool msgStart = false;
String serialReadFunc()
{
readedChar = '0';
readed = "";
while (Serial.available() > 0 || msgStart)
{
if (readedChar == MSG_START)
{
msgStart = true;
}
readedChar = (char)Serial.read();
if (readedChar == MSG_END)
{
msgStart = false;
break;
}
if (msgStart)
{
readed += readedChar;
}
}
return readed;
}
void setup()
{
Serial.begin(BAUD_RATE);
}
void loop()
{
if (serialReadFunc() == "MARCO")
{
Serial.println("MARCOCORRECT");
}
else
Serial.println(readed);
}
Console Image On Proteus
Console Image Proteus
I suspect you're having synchronization issues. I may be wrong, though, and I'm unable to test it at the moment.
I'd recommend trying to insert a delay on the sender, like so:
String readed;
while (Serial.available() > 0)
{
readed += Serial.read();
}
delay(10);
Serial.println("#MARCO*");
It would also be interesting to see the return value of the reader Serial.available(). Again, not 100% sure, but I believe the buffer may be full (the buffer holds 64 bytes).

how to read char array from serial monitor and command arduino accordingly?

currently, I am working on a project to read char inputs from serial monitor and command Arduino to switch on/off specific pins. The problem I am facing is, I am unable to read the complete char array entered in the serial monitor. can anyone tell me what am I doing wrong?
#define X 13 //led pin
char txt[15];
int i;
int Status=0;
void setup() { // put your setup code here, to run once:
pinMode(X,OUTPUT);// setting the pin flow of control as output
Serial.begin(9600);
while(!Serial)
{
; //to wait for pc to connect
}
Serial.println("\nHome Automation");
dashprint();
}
void loop() { // put your main code here, to run repeatedly:
if(Serial.available()>0)
{ i=0;
while(Serial.available()>0) //if serial available
{ char inchar=Serial.read();
txt[i]=inchar; // add char to txt string
i++;// increment to where to write next
txt[i]='\0'; //null termination
}
Serial.print(txt);
check();
}
}
void dashprint() //to print dashes
{
Serial.println("-----------------------------------------------");
Serial.println("give me some command"); //ask for command
}
void check()
{ if(strncmp(txt,"ON",2)==0)
{
digitalWrite(X,HIGH);
Status=1;
}
else if(strncmp(txt,"OFF",3)==0)
{ digitalWrite(X,LOW);
Status=0;
}
else if(txt=="STATUS")
{
}
else Serial.println("ERROR");
}
output:
Home Automation
give me some command
OERROR
NERROR
ERROR
expected output:
Home Automation
give me some command
ON
Your arduino is too fast to read the text "ON" in one round.
9600 is 1 ms per character.
A simple workaround is, to add a little delay
if(Serial.available()>0) {
delay(3); // wait for the whole message
i=0;
while(Serial.available()>0) {
...
ADD:
Additionally, you obviously receive a '\n' (newline) character. Make sure it's not causing troubles.
And increase the delay or have a better approach in general, if you expect more than 3 characters ( "STATUS" )
struct MYObject {char a[256];};
//structure works well with EEPROM put and get functions.
//also lets to input large strings, more then 64 bytes, as http
void setup() {
MYObject str ={" "};
Serial.begin(115200);
while (!Serial.available()) delay (10); //wait for string
int i = 0;
int k= Serial.available();
while (k > 0){
char inchar = Serial.read(); //read one by one character
str.a[i] = inchar;
i++;
if (k < 3) delay (10); //it gives possibility to collect more characters on stream
k = Serial.available();
}
str.a[i]='\0'; //null terminator
//now lets see result
Serial.println(str.a);
//.....
}

Receive data via uart for pic16F788 :mikroC

I've written the java code to send data to pic via serial port and now I need to program the microcontroller to read the data and make PortD.RD6=1 if the it receives 1 and PortD.RD6=0 if it receives 0. I've tried this code but I get many errors .
This is my first mikroC program so I really don't know how to manage these errors.
char output[1];
unsigned short i;
void main(){
TRISD = 0x01;
i = 0;
UART1_Init(9600);
while (1) {
if (UART1_Data_Ready()==1) {
i = UART1_Read(); // read the received data
ByteToStr(i, output);
if (output = "1" ) // this is where I get the error
{PortD.RD6=1;}
else { PortD.RD6=0;}
}}}
One error that I can spot is that ByteToStr returns three characters so it is probably overwriting other memory areas and giving an undefined result. You don't need to do that conversion you can simply read a byte into a char and do a comparison directly on that as follows:
void main()
{
char c;
TRISD = 0x01;
UART1_Init(9600);
while (1) {
if (UART1_Data_Ready()) {
c = UART1_Read();
if (c == '1')
PortD.RD6=1;
else
PortD.RD6=0;
}
}
}

Arduino Serial communication output

I have 2 Arduinos Leonardo and I want them to communicate itself, so I did the following code:
void setup() {
Serial.begin(9600);
Serial1.begin(9600);
}
void loop() {
String outMessage = ""; // String to hold input
while (Serial.available() > 0) { // check if at least 1 char is available
char inChar = Serial.read();
outMessage.concat(inChar); // add inChar to outMessage
}
if (outMessage != "") {
Serial.println("Sent: " + outMessage); // View Arduino 1 in Serial Monitor 1
Serial1.print(outMessage); // Send to Arduino 2
}
while (Serial1.available() > 0) {
Serial.print("Received: "); // View Arduino 1 in Serial Monitor 2
Serial.print(Serial1.read()); // Received from Arduino 1
Serial.println();
}
}
I want to send a message from Arduino 1, print in Serial Monitor and send via TX1 to Arduino 2 and vice-versa. The problem is that I don't receive what I was expecting. For instance if I type test:
Arduino 1:
Sent: test
Arduino 2:
Received: t
Received: e
Received: s
Received: t
I also tryed to do the receiving side like the sending side and use Serial.write but with no sucess.
Is there a easier way to do that or to fix it?
Thanks
Has mentioned by Hans, you need a protocol.
This is what I use to consider a message in Arduino to be a complete message:
char inData[10];
int index;
boolean started = false;
boolean ended = false;
String message =("I am Arduino 1 and I am ready");
void setup(){
Serial.begin(9600);
Serial.println(message);
}
void loop()
{
while(Serial.available() > 0)
{
char aChar = Serial.read();
if(aChar == '>')
{
started = true;
index = 0;
inData[index] = '\0';
}
else if(aChar == '<')
{
ended = true;
}
else if(started)
{
inData[index] = aChar;
index++;
inData[index] = '\0';
}
}
if(started && ended)
{
int inInt = atoi(inData);
Serial.println(inInt);
}
// Get ready for the next time
started = false;
ended = false;
index = 0;
inData[index] = '\0';
}
So, basically a message is considered completed only if it is between the special characters ><, like this: >message<. Then you can do the same on reading.
It does not have to be too complicated. If you look carefully at your last whlie-loop you can see that the software does not get a chance to read more than one character each time it passes through the loop. So that is what you get: one character at a time.
In your first while-loop you did better: you collected all the incoming letters until nothing was available and then sent them all at once. So if you make your last loop look more like the first one, you'll get a better result.
As mentioned a protocol to frame messages is needed between devices. A quick way to do this is to use Bill Porter's EasyTransfer library which does exactly what you are trying to do, over either UART or I2C. It has several examples.
Serial.read() reads only one byte every time you use it. A simple solution would be to store each byte on a char array while Serial.available>0 and then print the String with the whole message that was sent.
char message[40];
int count = 0;
while(Serial.available()>0){
message[count++] = Serial.read();
}
Serial.println(message);

Resources