I´m facing a problem with an application in Arduino Uno.
The board has a sensor that its counting products every second, after some time it sends the number of products to the server however this process takes more than a second, so the code that it is registering the products is not called until this process is completed so a piece of product sometimes is not counted.
I´ve been looking if Arduino supports multi-threading in order to have a thread for sending data to the server and the other one for registering the number of products, but i have no clear answer so far.
What would be the best solution to face this problem?
const long MAX_ITERATION = 100000;
const int OFF = 1;
const int ON = 0;
const int PHOTOELECTRIC_SENSOR = 3;
int counter = 0;
long iteration = 0;
int state = OFF;
void loop() {
registerProduct();
if (iteration >= MAX_ITERATION) {
// this process takes more than a second
sendDataToServer();
iteration = 0;
}
iteration++;
}
void registerProduct() {
int currentSensorState = digitalRead(PHOTOELECTRIC_SENSOR);
if (currentSensorState != state) {
if (currentSensorState == ON) {
counter++;
}
}
state = currentSensorState;
}
void sendDataToServer() {
// Sends data through HTTP protocol, and sets counter to zero
}
It looks like you might want to redesign this. While you might want to use something like threading on a desktop platform you don't have any hardware support for concurrency in that manner on the Arduino UNO. You do however have interrupts which you can use for your current problem.
Put the sensor on a pin change interrupt. Increment the counter in the ISR for that pin change interrupt. Arduino UNO has a few general purpose pin change interrupts, look at the datasheet for more info.
Then create a timer by using one of the internal timers. Attach this to an interrupt, when the timer interrupt fires take the counter amount and then put this aside. You will need to then send that value over to the server. Try to make the send not block. You may need to service the send in the main loop over multiple loop cycles.
By using the interrupts, especially the timing ones, you will free up a lot of processor cycles. Try to keep the amount of code in each of the ISRs as minimal as possible so that you don't lose data from interrupts being missed.
There is no concurrency in the microcontroller hardware or the language.
The correct way to do this is use an interrupt to accept the updates form the sensor asynchronously.
You should also not block on the send, you should send a few bytes and then send a few more on every loop through.
Using interrupts would be the preferred method, but you can also get away with using a simple or timed scheduler.
I've been working on a project that required one a while ago and you can find the source code here. It's based on a more extensive queuing library by Zuph called AVRQueue.
A simple implementation of the Scheduler library. I originally wrote it to be compiled with an avr-c compiler and haven't testing it with the arduino IDE but it shouldn't be an issue.
Scheduler m();
void setup() {
m.addTask(querySensor, "q_sens", 0, 1000);
m.addTask(doStuffWithData, "stuff", 0, 5000);
}
void loop() {
m.run(millis());
}
int querySensor(unsigned long now) {
...
}
int doStuffWithData(unsigned long now) {
...
}
Related
I am using MPU9250-breakout board with Arduino Uno.
The library I used is from here.
Below is my code.
#include <Arduino_FreeRTOS.h>
#include "mpu9250.h"
MPU9250 IMU(Wire,0x68);
int status;
void task_1(void *pvParameters)
{
(void) pvParameters;
for (;;)
{
}
}
void task_2(void *pvParameters)
{
(void) pvParameters;
for (;;)
{
}
}
void setup() {
Serial.begin(115200);
while(!Serial) {}
status = IMU.begin();
if (status < 0) {
Serial.println("IMU initialization unsuccessful");
Serial.println("Check IMU wiring or try cycling power");
Serial.print("Status: ");
Serial.println(status);
while(1) {}
}
xTaskCreate(
task_2,
(const portCHAR *)"task2", // A name just for humans
128, // Stack size
NULL,
1, // priority
NULL);
xTaskCreate(
task_1,
(const portCHAR *)"task1", // A name just for humans
128, // Stack size
NULL,
1, // priority
NULL);
}
void loop()
{
}
The problem is that when there are two tasks defined, the program will be restarted automatically. But when I comment out task_1, the program works fine. The result value of xTaskCreate is correct.
I guess the problem might be the stack or heap size is too small, but I've increased stack and heap size and it's still doesn't work.
Can anyone tell me where the problem might be from?
At the end of your setup(), you need to start the scheduler:
// Now the task scheduler, which takes over control of scheduling individual tasks, //is automatically started.
vTaskStartScheduler();
That is all I see different between my project which works and yours.
Once you have created your tasks, you have to start scheduler.
Call vTaskStartScheduler() before exiting setup function and after you have created your tasks.
https://www.freertos.org/a00132.html
Just for the info, Arduino-UNO (with ATMega-328P) has very limited RAM and it may happen some tasks won't be created. Check return value of xTaskCreate functions.
When I run into this problem, it's usually been that my interrupt vectors weren't pointing to appropriate handlers. So when the RTOS needed to do a context switch, for example, it jumped off into la-la land. Since you say that taking out the tasks allows it to run to the library call, but fails in the same way, it is possible none of your handlers are setup correctly.
The FreeRTOS website has an FAQ about getting new projects to run that I would suggest reading through to help troubleshoot this kind of problem:
https://www.freertos.org/FAQHelp.html#faq
You might also look at some of the other AVR examples included with FreeRTOS to see how they have interrupts setup: https://www.freertos.org/a00090.html#ATMEL
I have a qt program. I have CAN requests that I want to send in sequential order.
I want to wait for answers, before sending other requests.
SendReadLatchCommand(fam,prod,addr,0x00000000, 4); // 1st request
// wait for answer and analyze it??
SendReadLatchCommand(fam,prod,addr,0x00000002, 4); // 2nd request
I have a receiveData() method, called by my thread of reception, where I save the received message.
I want to sleep in my main program and we awake when receiving answer.
I can't use signal/slot because in the slot, I don't know what is the last request I sent, so I can't continue emitting requests.
How can I do this?
thanks
If i understand you properly, you wanted to process the request synchronously.
Look into the QEventLoop in the qtdoc, you can do it this way:
QEventLoop wait_loop;
// 1st request
connect(request_1, SIGNAL(sig_answer_arrived()), &wait_loop, SLOT(quit()));
request_1->send_request();
wait_loop.exec();
// here we already got the answer
analyze_answer();
// the 2nd request does the same
I'm not sure whether it is a good idea to block your main thread, however it can be done by using a binary semaphore, which is the same as a counting semaphore with a maxCount of 1. Therefore one can use a counting semaphore QSemaphore
Typically, a QSemaphore is implemented in terms of QWaitCondition (refer Qt help). One could block on a wait condition until the CAN thread signals the wait condition. One can hide the blocking on the wait behind some interface e.g:
//--- Very simple implementation - concept only
QWaitCondition cond_;
QMutex mutex_;
void rxThreadHandler( /*args*/ )
{
while( !quitCalled() )
{
waitOnReceivedData();//Blocks, I assume...
handleReceivedData();
answerRxd();
}
}
void answerRxd()
{
QMutexLocker lock( mutex_ );
cond_.wakeAll();
}
void sendNext( const Buffer& buffer )
{
QMutexLocker guard( mutex_ );
//Waits/Blocks until condition signalled, then locks mutex
// to prevent further signalling (might block rx thread)
cond_.wait( lock.mutex() );
//Unlocking mutex explicitly to allow receipt of data
guard.unlock();
//Now send as result of previous receive. This does not
// prevent receiving thread...
sendNextImpl( const Buffer& buffer );
}
I've researched a bit, and I've ran into a couple of examples of how buttons are used as interrupts. However, the design I'm trying to implement uses analog sensors. Right now, what I want to do is to have my analog sensors flag a boolean to tell the interrupt to execute, not a button. How would I do so?
This is what I have thought up based on what I researched:
boolean isWall;
attachInterrupt(isWall, interruptFunction, RISING);
void loop() {
if(analogSensor.response > 450) {
isWall = true;
}
normalExecution(); // what it normally does if isWall is false
}
void interruptFunction() {
// code implementation
isWall = false; // set isWall back to false after executing interruptFunction
}
void normalExecution() {
// foo
}
Can someone verify?
Perhaps I am completely wrong but it has always been my understanding that interrupts in Arduino are based on the voltage seen by a pin - i.e. they are hardware interrupts. Consequently, while your code is correct for a hardware interrupt, it will not work for a change in a variable.
That said, this link and this link discuss Analog Comparator methods for accomplishing what you are trying to do.
Can anyone tell me if I'm doing this right?
Using Qt I'm implementing a TCP Server by inheriting from the QTcpServer class. On an incoming connection I create a new thread, a new Worker object, and I move the object to the new thread and start the thread. From here, the server keeps listening for new clients and each thread then is in its run method for object Worker.
Now, I create a timer because I need to send updates to each client based on 1 second intervals AND when a song is playing. In the readyRead slot I read data using readAll and then perform some work and send a reply.
However, when I go back to my run method I need to just continue sending song data updates to the clients (with no response from the client). Should this all just go in a while(true) loop and then I check some boolean to start and stop the timer? The track information I need to send is the song progression time.
I guess my question is, should I be doing it this way? It seems a little complex, but then again that's concurrency for you. Basically I need the TCP server to send data to the client repeatedly when some condition is true. I feel like just an endless while loop that checks when to start and stop the timer is useless work.
Would posting code make this clearer?
This question is a very old one, but perhaps it could still help.
About threads in Qt:
Many people think about parallel processing in Qt like in .NET where you need for every operation another thread, in qt this is not necessary!
In qt you only need a thread if you have blocking code like calculating big things or waiting syncron for an answer from a SQLServer
If i have understand you correctly you don't have such a blocking operation.
So i have programmed a very small TcpServer without inheriting and without a single thread (except the main eventloop thread of course), which hopefully solves your problem and help others:
#include <QObject>
#include <QSet>
#include <QTcpServer>
#include <QTcpSocket>
#include <QTimer>
class TcpServer : public QObject
{
Q_OBJECT
public:
TcpServer()
{
// handle new connections
this->connect(&this->serverTcp, &QTcpServer::newConnection, this, &TcpServer::handleClientConnect);
// init client refresh timer
this->timer.setInterval(1000);
this->connect(&this->timer, &QTimer::timeout, this, &TcpServer::handleClientUpdates);
this->timer.start();
}
bool startListen(qint16 port)
{
return this->serverTcp.listen(QHostAddress::Any, port);
}
private slots:
void handleClientConnect()
{
QTcpSocket* socketClient = *this->setConnectedClients.insert(this->serverTcp.nextPendingConnection());
this->connect(socketClient, &QTcpSocket::disconnected, this, &TcpServer::handleClientDisconnect);
this->connect(socketClient, &QTcpSocket::readyRead, this, &TcpServer::handleClientData);
}
void handleClientDisconnect()
{
this->setConnectedClients.remove((QTcpSocket*)this->sender());
}
void handleClientData()
{
QTcpSocket* socketSender = (QTcpSocket*)this->sender();
// handle here the data sent by the client
}
void handleClientUpdates()
{
// construct here your update data
QByteArray baUpdateResponse = "test";
// send update data to all connected clients
foreach(QTcpSocket* socketClient, this->setConnectedClients) {
socketClient->write(baUpdateResponse);
}
}
private:
QTcpServer serverTcp;
QTimer timer;
QSet<QTcpSocket*> setConnectedClients;
};
Environment: Ubuntu, Qt Creator
In my Qt app, I found that sometimes Qt doesn't respond to my key press event immediately, but if I wait a while, it eventually responds.
I think something is blocking the UI.
As I know, if a Qt's component (QWidget etc.) is being destroyed, the Qt UI will be blocked. I have checked my code, there is no component being destroyed at the time I'm pressing the up/down key.
I really want to know is there any other things can block Qt UI.
{
...
connect(webViewWidget, SIGNAL(loadfinished()), this, SLOT(addItem()));
...
}
void addItem()
{
delete webViewWidget; // will this delete block UI?
mListWidget = new ScrollWidget();
mScrollArea = new ScrollArea(this);
for(int i=0; i<Datalen; i++)
{
mListWidget->addSubItem(itemWidget);
}
}
void keyPressEvent(QKeyEvent *event)
{
switch(event->key)
{
case UP_KEY:
scroll up;
break;
case DOWN_KEY:
scroll down;
break;
default:
break;
}
}
In general, your key press event will not be processed before all other events which were put into the application's event queue before pressing your key are processed.
Therefore it could be any kind of event which has not finished processing. Maybe you can figure out if there are any events, e.g. by using QApplication::hasPendingEvents or by inheriting from QApplication and adding debug output whenever an event is added or fully processed.
Destruction of objects is usually not a concern, unless you are doing a lot of work in the destructor. Destroying a webview may take long. You probably should not be destroying it like you do. Instrument that delete (see code below) and see how long it takes.
Your own code may be calling APIs that block. Are you calling any third party libraries? Are you calling any wait... methods in Qt's own API?
If you're unsure, you can instrument every slot and every reimplemented virtual method like xxxEvent(...). You'd need to instrument only slots and reimplemented QObject/QWidget methods, not every method in your code.
You may be producing an event storm, perhaps by posting lots of events in a loop, or by sending a lot of signals that are hooked up to slots connected via a Qt::QueuedConnection. Make sure you're not calling repaint() from within paintEvent() for example.
The instrumentation example below uses RAII and is very easy to apply. Alternatively, you can use a profiler.
#include <QElapsedTimer>
#define INSTRUMENT() Instrument instr__ument(__FUNCTION__)
#define INSTRUMENTLIM(lim) Instrument instr__ument(__FUNCTION__, (lim))
class Instrument {
QElapsedTimer timer;
int limit;
const char * function;
public:
Instrument(const char * name, int timeLimitMs = 20) :
function(name), limit(timeLimitMs) { timer.start(); }
~Instrument() {
if (timer.elapsed() > limit) {
qDebug("%s was slow, took %d ms", function, timer.elapsed());
}
}
}
void slot(...)
{
INSTRUMENT();
...
}
void addItem()
{
INSTRUMENT();
delete webViewWidget; // will this delete block UI?
mListWidget = new ScrollWidget();
mScrollArea = new ScrollArea(this);
for(int i=0; i<Datalen; i++)
{
mListWidget->addSubItem(itemWidget);
}
}