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
Related
I am fairly new to coding and especially to C++ but usually with enough googling and breaking problems down to simpler blocks I can figure things out. This issue makes no sense to me though and the solution I just happened to come up with on accident makes even less sense to me.
I am writing a program for ESP32-S in vscode with platformio and broke this down to isolate what was causing the error and found this issue with class/object declaration:
This code will compile but I get a link error twice that says
undefined reference to `point::point()'
#include <Arduino.h>
class point {
public:
point();
point(uint day){
this->_day = day;
}
uint _day;
};
class channel {
public:
channel(String _color, byte _pin){
}
point _points[64];
};
channel red("red", 0);
void setup() {}
void loop() {}
Meanwhile this code with one seemingly unrelated change compiles and links without issue:
#include <Arduino.h>
class point {
public:
point();
point(uint day){
this->_day = day;
}
uint _day;
};
class channel {
public:
channel(){ // <--- Removing the arguments from channel constructor fixes it?
}
point _points[64];
};
channel red(); // <--- And here of course
void setup() {}
void loop() {}
I don't know why that fixes it, and I have a workaround for now if this is what I have to do, but I want to understand. Thanks.
You've declared a constructor point::point(), but not defined it (i.e. it has no body). This is not OK with the linker and that's what you're being told.
There are three ways to fix this.
Don't declare the constructor (compiler generates a default constructor which may or may not initialize the member _day to 0, depending on compiler and platform). Note that you also have the interesting alternative of deleting the default constructor.
Declare and define it to do whatever you consider appropriate.
Give your constructor point::point(uint day) a default argument value, e.g.: point::point(uint day = 0).
Side note on C style arrays of C++ objects like here:
point _points[64];
This is a dangerous combination, unless you know exactly what you're doing. See the C++ FAQ
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) {
...
}
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);
}
}