Help with signal/slots in a worker thread running an infinite loop!
-
Hi! I have and issue where I can't get a signal-slot connection to work in a worker thread when its running a loop, but I tried implementing QCoreApplication::processEvents() and am still having trouble. I'm using Qt 5.15. For context, I am using a stepping motor that oscillates between 2 endpoints in an infinite while loop until asked to stop (currently I use a global variable in the main thread to stop the motion, BUT am unsure if that is the "proper" way to do that - I don't know if there are advantages to calling a function in the worker thread to do so instead). I have other threads / functions that use the exact same global var mechanism to operate, and they work - whereas this one does not. I am trying to interrupt that oscillating motion by destroying the worker thread and then creating a new worker thread. Any help would be suuuuper appreciated. Thanks!!!!
threadController inherits (is this the right term?) information from another QObject called systemHandler. systemHandler houses all the relevant data for the motors (ie motor positions). threadController handles the creation and deletion of threads and runs in the main thread. theadController creates new motorController QObjects and moves them into threads. I made motorController a child of systemHandler because I want to make a "snapshot" of the system's values whenever I direct the program to begin a motor movement - kinda like loading a cassette tape with all the pre-programmed moves into a machine.
threadController.cpp
#include "threadcontroller.h" #include "motorcontrollerclasses.h" #include "serversocket.h" #include <QObject> #include <QThread> #include <QDebug> threadController::threadController(System *systemHandler, QObject *parent) : QObject{parent} , m_systemHandler(systemHandler) { } void threadController::startMotorThread() //The "spin" motor thread is an example of the infinite loop in a worker thread that is working for me. { qDebug("threadController startMotorThread() called"); stopFlag = 0; if (m_systemHandler->magnetSpinRate() > 0) { startSpinThread(); emit userRequestStartSpin(); } } void threadController::startSpinThread() { qDebug("startSpinThread() called"); QThread *spinQThread = new QThread(); //Pointer To QThread spinQThread->setObjectName("spinThread"); motorController *spinMotor = new motorController(*m_systemHandler); spinMotor->moveToThread(spinQThread); QObject::connect(spinMotor, &motorController::destroyMotorThreadSpin, spinMotor, &motorController::deleteLater); QObject::connect(spinMotor, &motorController::destroyMotorThreadSpin, spinQThread, &QThread::quit); QObject::connect(spinQThread, &QThread::finished, spinQThread, &QThread::deleteLater); QObject::connect(this, &threadController::userRequestStartSpin, spinMotor, &motorController::controlSpin); spinQThread->start(); } void threadController::stopMotorThread() //stopFlag shuts down ALL of my motors at once - I don't want to use every time for my adjustSweep function (in motorController). { stopFlag = 1; qDebug("threadController stopMotorThread() called"); } void threadController::startAdjustSweepMotorThread() //the "adjustSweep" is the one I am having trouble with interrupting and destroying the thread. { stopAdjustSweepFlag = 0; //stopAdjustSweepFlag is my global var. A value of 1 is supposed to interrupt the sweep. I was noodling around and am using 2 methods to try and stop it - global var and calling a method. startAdjustSweepThread(); emit startAdjustSweepSignal(); } void threadController::startAdjustSweepThread() { qDebug("startAdjustSweepThread called"); QThread *adjustSweepQThread = new QThread(); //Pointer To QThread adjustSweepQThread->setObjectName("adjustSweepThread"); motorController *adjustSweepMotor = new motorController(*m_systemHandler); //(m_systemHandler, this); adjustSweepMotor->moveToThread(adjustSweepQThread); QObject::connect(this, &threadController::threadStopAdjustSweepSignal, adjustSweepMotor, &motorController::stopAdjustSweep, Qt::QueuedConnection); //This signal is successfully emitted, but the slot is never called! QObject::connect(this, &threadController::threadStopAdjustSweepSignal, adjustSweepMotor, &motorController::test, Qt::QueuedConnection); //Similar story to the above! QObject::connect(adjustSweepMotor, &motorController::destroyMotorThreadAdjustSweep, adjustSweepMotor, &motorController::deleteLater); QObject::connect(adjustSweepMotor, &motorController::destroyMotorThreadAdjustSweep, adjustSweepQThread, &QThread::quit); QObject::connect(adjustSweepQThread, &QThread::finished, adjustSweepQThread, &QThread::deleteLater); QObject::connect(this, &threadController::startAdjustSweepSignal, adjustSweepMotor, &motorController::adjustSweep, Qt::QueuedConnection); //Below is what chatGPT told me to try, I get the signal received statement, but the invokeMethod() doesn't work and can't find the function. // QObject::connect(this, &threadController::threadStopAdjustSweepSignal, []() { // qDebug() << "Signal threadStopAdjustSweepSignal received"; // }); //QMetaObject::invokeMethod(adjustSweepMotor, "stopAdjustSweep", Qt::QueuedConnection); adjustSweepQThread->start(); }
threadController.h
#ifndef THREADCONTROLLER_H #define THREADCONTROLLER_H #include <QObject> #include "system.h" class threadController : public QObject { Q_OBJECT public: explicit threadController(System *systemHandler, QObject *parent = nullptr); //explicit threadController(QObject *parent = nullptr); public slots: void startMotorThread(); void stopMotorThread(); void stopRotateMotorThread(); void startRotateMotorThreadPrecise(); void startAdjustMotorThread(); void startAdjustSweepMotorThread(); void startSpinThread(); void startRollThread(); void startAdjustThread(); void startAdjustSweepThread(); void startRotateThreadPrecise(); void startInitializeThread(); void startStowThread(); void startStowRotateThread(); void startInitializeRotateThread(); void startInitializeRollThread(); void rollSignalNotifier(); void rotateSignalNotifier(); void rotateStowSignalNotifier(); void stopAdjustRollCalled(); void stopAdjustSweepCalled(); signals: //void userRequestStart(); void userRequestStartSpin(); void userRequestStartRoll(); void userRequestStartRotatePrecise(); void userRequestStartInitializeRotate(); void userRequestStartInitializeRoll(); void userRequestStartStowRotate(); void startAdjustRollSignal(); void startAdjustSweepSignal(); void threadStopAdjustSweepSignal(); private: System *m_systemHandler; }; extern int stopFlag; //This is the stopFlag to initiate stopping of the motors. extern int stopRotate; //StopFlag to stop rotate motors. extern int stopSpinFlag; extern int stopRollFlag; extern int stopAdjustRollFlag; //stopFlag to end the adjust movement extern int stopAdjustSweepFlag; //stopFlag to end sweep movement. #endif // THREADCONTROLLER_H
motorController is a child of systemHandler. It runs the motors and is designed to be a snapshot of systemHandler.
motorcontrollerclasses.cpp
motorController::motorController(System &systemHandler) : m_systemHandler(systemHandler) { //nothing in the constructor is relevant. mrollAngle = m_systemHandler.rollAngle(); mrollRate = m_systemHandler.rollRate(); mreqStartingAngle = m_systemHandler.startingAngle(); dwellDelay = m_systemHandler.dwellLength(); mrollDirection = m_systemHandler.rollDirection(); magnetSpinRate = m_systemHandler.magnetSpinRate(); mmagnetDirection = m_systemHandler.magnetDirection(); mreqRotateDirection = m_systemHandler.rotateDirection(); mstoredRotateDirection = m_systemHandler.storedRotateDirection(); mstoredStartingAngle = m_systemHandler.storedStartingAngle(); mstoredMainHeight = m_systemHandler.storedMainHeight(); mmainHeight = m_systemHandler.mainHeight(); mstoredTelescopeLength = m_systemHandler.storedTelescopeLength(); mtelescopeLength = m_systemHandler.telescopeLength(); mrotateRange = m_systemHandler.rotateRange(); mrotateRate = m_systemHandler.rotateRate(); mrotateDwell = m_systemHandler.rotateDwell(); mrotateDirectionPrecise = m_systemHandler.rotateDirectionPrecise(); mloggedRotate = m_systemHandler.loggedRotate(); mloggedRoll = m_systemHandler.loggedRoll(); madjustDir = m_systemHandler.adjustDir(); mrotateSteps = 0; mrollSteps = 0; mrollScanHits = 0; mrotateScanHits = 0; } void motorController::controlSpin() //This is the function that works properly. { float degreesPerSecFromHz = magnetSpinRate*360; //convert magnetSpinRate (hz aka rev/s) to Degrees/s float targetMagnetSpeed = getMagnetSpeed(degreesPerSecFromHz); // The target speed you want to reach QString motorUsed = "spin"; float currentSpeed = 0; int stepsTaken = 0; qDebug() << "controlSpin() called"; while(stopFlag==0) { moveOneStep(targetMagnetSpeed, stepPinNegSpin, stepPinPosSpin, motorUsed); gpioDelay(getAccelDelay(stepsTaken)); stepsTaken++; } if (stopFlag == 1) { qDebug() << "controlSpin() is breaking"; stepsTaken = 0; for (int i = 0; i <200; i++) { moveOneStep(targetMagnetSpeed, stepPinNegSpin, stepPinPosSpin, motorUsed); stepsTaken++; gpioDelay(getDecelDelay(stepsTaken)); } emit destroyMotorThreadSpin(); } } void motorController::adjustSweep() //this is the code that won't interrupt! In either while loop, when I emit threadStopAdjustSweepSignal, the stopAdjustSweepFlag global variable never changes! { mstopAdjustSweep = false; qDebug() << "adjustSweep called!"; float halfRangeTotalSteps = (mrollAngle/2/360)*stepsPerRev*gearRatioWorm; bool mstopSetFlag = false; int halfRangeStepsTaken = 0; float halfRangeToDegrees = 0; float halfRangeRollTracker = 0; serverSocket rollNotifier; QString data; float setupAdjustSpeed = getSweepSpeed(3); //please change me once //now we move to the half distance. setDirection(clockwise, directionPinPosRoll , directionPinNegRoll); while (!mstopSetFlag && !mstopAdjustSweep && stopAdjustSweepFlag == 0) { //normally using stopAdjustSweepFlag if (stopFlag==1) { mstopSetFlag = true; } if (halfRangeStepsTaken >= halfRangeTotalSteps) { mstopSetFlag = true; } moveOneStep(setupAdjustSpeed, stepPinNegRoll, stepPinPosRoll, "roll"); halfRangeStepsTaken++; halfRangeToDegrees = (halfRangeStepsTaken*360)/stepsPerRev/gearRatioWorm; if (clockwise) { halfRangeRollTracker = mstoredStartingAngle-halfRangeToDegrees; } else { halfRangeRollTracker = mstoredStartingAngle+halfRangeToDegrees; } if (halfRangeStepsTaken%20 == 0) { data = "storedRollStartAngle: " + QString::number(halfRangeRollTracker); rollNotifier.sendUpdate(data); } QCoreApplication::processEvents(); //Listen to events!! //QThread::msleep(5); } qDebug() << "We finished the move phase"; //qDebug() << "stopAdjustSweepFlag is in motorController: " << stopAdjustSweepFlag; mstoredStartingAngle = halfRangeRollTracker; clockwise = !clockwise; //setDirection(clockwise, directionPinNegRoll, directionPinPosRoll); setDirection(clockwise, directionPinPosRoll , directionPinNegRoll); //Now we begin the normal rotation series. float oscilTotalSteps = (mrollAngle/360)*stepsPerRev*gearRatioWorm; int oscilStepsTaken = 0; float oscilRollTracker = halfRangeRollTracker; float oscilToDegrees=0; if(mrollRate ==0) { mrollRate = 3; } if (mrollRate != 0) { qDebug() << "We are in the oscillation phase"; while (stopFlag == 0 && !mstopAdjustSweep && stopAdjustSweepFlag == 0) { if (oscilStepsTaken >= oscilTotalSteps) { //You've hit the end of the oscillation. Time to flip and reverse. clockwise = !clockwise; //setDirection(clockwise, directionPinNegRoll, directionPinPosRoll); setDirection(clockwise, directionPinPosRoll , directionPinNegRoll); mstoredStartingAngle = oscilRollTracker; oscilStepsTaken = 0; } moveOneStep(setupAdjustSpeed, stepPinNegRoll, stepPinPosRoll, "roll"); //change setupAdjustSpeed to rollSpeed!!!! oscilStepsTaken++; oscilToDegrees = (oscilStepsTaken*360)/stepsPerRev/gearRatioWorm; if (clockwise) { oscilRollTracker = mstoredStartingAngle-oscilToDegrees; } else { oscilRollTracker = mstoredStartingAngle+oscilToDegrees; } if (oscilStepsTaken%20 == 0) { data = "storedRollStartAngle: " + QString::number(oscilRollTracker); rollNotifier.sendUpdate(data); } QCoreApplication::processEvents(); //Listen to events!! //QThread::msleep(5); } } //qDebug() << "stopAdjustSweepFlag pt 2 in motorcontroller is: " << stopAdjustSweepFlag; qDebug() << "adjustSweep() is breaking"; data = "storedRollStartAngle: " + QString::number(oscilRollTracker); rollNotifier.sendUpdate(data); //Sending stored information. emit destroyMotorThreadAdjustSweep(); } void motorController::stopAdjustSweep() //never called :( { mstopAdjustSweep = true; qDebug() << "stopAdjustSweepCalled, mstopAdjustSweep is: " << mstopAdjustSweep; }
motorcontrollerclasses.h
[CODE]#ifndef MOTORCONTROLLERCLASSES_H #define MOTORCONTROLLERCLASSES_H #include "system.h" #include <iostream> #include <pigpio.h> #include <fstream> #include <limits> #include <math.h> #include <thread> #include <QObject> //motorController is a child of System, so it inherits from it. class motorController : public System { Q_OBJECT public: explicit motorController(System &systemHandler); void checkSlip(); void initializeRoll(); void initializeRotate(); void stowRotate(); void controlSpin(); //pass magnet spin rate and spin until stop command or a certain timeout. void controlRoll(); //Control roll angle and roll rate. void adjustRoll(); void adjustSweep(); void stopAdjustRoll(); void moveOneStep(float stepDelay, int stepPinNeg, int stepPinPos, QString motorType); void checkSensor(int sensorPinScan); void emitDestroyMotorThread(); //allows us to destroy the motor thread when the stop banner is clicked. In use for the qsAdjust chain. void moveRevolution(float revolutions, bool clockwise, float stepDelay, int directionPinNeg, int directionPinPos, int stepPinNeg, int stepPinPos); void moveRollRevolution(float revolutions, bool clockwise, float stepDelay, int directionPinNeg, int directionPinPos, int stepPinNeg, int stepPinPos); void changeAdjustDir(bool newValue); void setDirection(bool clockwise, int directionPinNeg, int directionPinPos); float getMagnetSpeed(float inputSpeed); float getSweepSpeed(float inputSpeed); float getAccelDelay(int inputSteps); float getDecelDelay(int inputSteps); bool clockwise = true; float spinSpeed; float rollSpeed; float rotateSpeed; float inputSpeed; float rotatePreciseSpeed; //below is new and need to be implemented, main and telescope do not need to be in Server Controller. void controlRotatePrecise(); void stopAdjustSweep(); void test(); signals: void finished(); void destroyMotorThreadSpin(); void destroyMotorThreadRoll(); void destroyMotorThreadAdjustSweep(); void destroyMotorThreadInitRotate(); void destroyMotorThreadInitRoll(); void destroyMotorThreadStowRotate(); void destroyMotorThreadAdjust(); void destroyMotorThreadMain(); void destroyMotorThreadTelescope(); void destroyMotorThreadRotatePrecise(); void motorInitializeRotateSuccess(); void motorInitializeRollSuccess(); void motorStowRotateSuccess(); private: System& m_systemHandler; float magnetSpinRate; bool mmagnetDirection; float mrollAngle; float mrollRate; bool mrollDirection; bool mrotateDirectionPrecise; int dwellDelay; float mreqStartingAngle; float mreqRotateDirection; float mstoredStartingAngle; float mstoredRotateDirection; float mrotateRate; float mrotateDwell; float mrotateRange; float mstoredTelescopeLength; float mstoredMainHeight; float mtelescopeLength; float mmainHeight; int mrollSteps; int mrollScanHits; int mrotateSteps; int mrotateScanHits; float mloggedRotate; float mloggedRoll; float checkRoll; float checkRotate; bool madjustDir; bool mstopAdjustSweep; }; extern float rollSteps; extern float rotateSteps; #endif // MOTORCONTROLLERCLASSES_H
And if by some miracle it's an issue with systemHandler:
systemHandler.h
#ifndef SYSTEM_H #define SYSTEM_H #include <QObject> #include <QTimer> //#include "motorcontrollerclasses.h" class System : public QObject { Q_OBJECT Q_PROPERTY(QString currentTime READ currentTime WRITE setCurrentTime NOTIFY currentTimeChanged) //Store the Roll Angle Range set by the GUI. Q_PROPERTY(float rollAngle READ rollAngle WRITE setRollAngle NOTIFY rollAngleChanged) //Store the Roll Rate set by the GUI. Q_PROPERTY(float rollRate READ rollRate WRITE setRollRate NOTIFY rollRateChanged) //Store User Requested Starting Angle set by the GUI. Q_PROPERTY(float startingAngle READ startingAngle WRITE setStartingAngle NOTIFY startingAngleChanged) //Store Actual Physical Location of the roll Angle Q_PROPERTY(float storedStartingAngle READ storedStartingAngle WRITE setStoredStartingAngle NOTIFY storedStartingAngleChanged) //Store Dwell Length set by GUI. Q_PROPERTY(int dwellLength READ dwellLength WRITE setDwellLength NOTIFY dwellLengthChanged) //Store Roll Direction set by GUI. Q_PROPERTY(int rollDirection READ rollDirection WRITE setRollDirection NOTIFY rollDirectionChanged) //Store Magnet Spin Rate set by GUI. Q_PROPERTY(float magnetSpinRate READ magnetSpinRate WRITE setMagnetSpinRate NOTIFY magnetSpinRateChanged) //Store Magnet Spin Direction set by GUI. This does not yet have functionality! Will need to add direction to MotorController Q_PROPERTY(bool magnetDirection READ magnetDirection WRITE setMagnetDirection NOTIFY magnetDirectionChanged) //Store User Requested Rotate Direction set by GUI. Q_PROPERTY(float rotateDirection READ rotateDirection WRITE setRotateDirection NOTIFY rotateDirectionChanged) //Store Actual Physical Location of the Rotate/Rotate angle. Q_PROPERTY(float storedRotateDirection READ storedRotateDirection WRITE setStoredRotateDirection NOTIFY storedRotateDirectionChanged) //Motor Running Boolean set by GUI. Q_PROPERTY(bool isRunning READ isRunning WRITE setIsRunning NOTIFY isRunningChanged) //Timer Length Stored by UI Q_PROPERTY(float timerLength READ timerLength WRITE setTimerLength NOTIFY timerLengthChanged) //Requested Main Height of the System set by GUI. Q_PROPERTY(float mainHeight READ mainHeight WRITE setMainHeight NOTIFY mainHeightChanged) //Stored Actual Physical Location of the Main Height of the WS. Q_PROPERTY(float storedMainHeight READ storedMainHeight WRITE setStoredMainHeight NOTIFY storedMainHeightChanged) //Direction of the Main Motor set by the GUI Q_PROPERTY(bool mainDirection READ mainDirection WRITE setMainDirection NOTIFY mainDirectionChanged) //Requested Telescope Length of the System set by GUI. Q_PROPERTY(float telescopeLength READ telescopeLength WRITE setTelescopeLength NOTIFY telescopeLengthChanged) //Stored Actual Physical Location of the Telescope Length of the WS. Q_PROPERTY(float storedTelescopeLength READ storedTelescopeLength WRITE setStoredTelescopeLength NOTIFY storedTelescopeLengthChanged) //Direction of Telecope Motor set by GUI. Q_PROPERTY(bool telescopeDirection READ telescopeDirection WRITE setTelescopeDirection NOTIFY telescopeDirectionChanged) //Request for precise rotate motor movement. Q_PROPERTY(bool startRotate READ startRotate WRITE setStartRotate NOTIFY startRotateChanged) //Rotate Direction Precise movement Direction. Used in HomeView when holding down left or right. Q_PROPERTY(bool rotateDirectionPrecise READ rotateDirectionPrecise WRITE setRotateDirectionPrecise NOTIFY rotateDirectionPreciseChanged) //Logged initial Rotate Position Q_PROPERTY(float loggedRotate READ loggedRotate WRITE setLoggedRotate NOTIFY loggedRotateChanged) //Logged initial Roll Position Q_PROPERTY(float loggedRoll READ loggedRoll WRITE setLoggedRoll NOTIFY loggedRollChanged) //EVERYTHING BELOW IS NEW! //Adds ability of rotate to roll. Can delete if need be. Q_PROPERTY(int rotateRange READ rotateRange WRITE setRotateRange NOTIFY rotateRangeChanged) Q_PROPERTY(float rotateRate READ rotateRate WRITE setRotateRate NOTIFY rotateRateChanged) Q_PROPERTY(int rotateDwell READ rotateDwell WRITE setRotateDwell NOTIFY rotateDwellChanged) //This property will control when to stop/start the motors. ClientSocket will send this to Server, which will be read. Q_PROPERTY(bool runMotors READ runMotors WRITE setRunMotors NOTIFY runMotorsChanged) //This property says whether we are moving forward with using the adjust feature while in the RUNNING state. Interrupts the sweep feature. Q_PROPERTY(bool startAdjustRoll READ startAdjustRoll WRITE setStartAdjustRoll NOTIFY startAdjustRollChanged) //This property controls the direction of the adjustDirection when using the adjust feature while in the RUNNING state. Q_PROPERTY(bool adjustDir READ adjustDir WRITE setAdjustDir NOTIFY adjustDirChanged) //This property tells us whether we are using the adjust sweep feature Q_PROPERTY(bool startAdjustSweep READ startAdjustSweep WRITE setStartAdjustSweep NOTIFY startAdjustSweepChanged) public: explicit System(QObject *parent = nullptr); //this will establish the System class with no data. QString currentTime() const; float rollAngle() const; float rollRate() const; float startingAngle() const; float storedStartingAngle() const; int dwellLength() const; int rollDirection() const; float magnetSpinRate() const; float rotateDirection() const; float storedRotateDirection() const; bool isRunning() const; float timerLength() const; int rotateRange() const; float rotateRate() const; int rotateDwell() const; bool magnetDirection() const; float mainHeight() const; float storedMainHeight() const; float telescopeLength() const; float storedTelescopeLength() const; bool runMotors() const; bool telescopeDirection() const; bool mainDirection() const; bool startRotate() const; bool rotateDirectionPrecise() const; float loggedRotate() const; float loggedRoll() const; bool startAdjustRoll() const; bool adjustDir() const; bool startAdjustSweep() const; //Main Pins const int stepPinPosMain = 19; const int stepPinNegMain = 26; const int directionPinPosMain = 20; const int directionPinNegMain = 21; const int sensorPinMain = 0; const int sensorPinWMain = 0; //Telescope Pins const int stepPinNegTelescope = 2; const int stepPinPosTelescope = 17; const int directionPinPosTelescope = 3; const int directionPinNegTelescope = 4; const int sensorPinTelescope = 0; const int sensorPinWTelescope = 0; //Spin Pins const int stepPinNegSpin = 26; const int stepPinPosSpin = 19; const int directionPinNegSpin = 21; const int directionPinPosSpin = 20; //Roll Pins const int stepPinNegRoll = 11; const int stepPinPosRoll = 9; const int directionPinNegRoll = 8; const int directionPinPosRoll = 25; //const int sensorPinRoll = 02; const int sensorPinWRoll = 7; //Rotate Pins const int directionPinNegRotate = 13; const int directionPinPosRotate = 12; const int stepPinNegRotate = 6; const int stepPinPosRotate = 5; const int sensorPinRotate = 16; //const int sensorPinWRotate = 7; const int sensorPinWRotate = 10; //16; const int stepsPerRev = 200; const float gearRatioWorm = 24*30/17; //96 teeth / 4 starts on worm * 30/17 pulley ratio. const double stepAngleWorm = 360/(stepsPerRev*gearRatioWorm); const float gearRatioMagnet = 2; //2:1 const float stepAngleMagnet = 360/(stepsPerRev*gearRatioMagnet); const float stepDelay = 100; //controls speed of initializeRoll and initializeRotate. 100 is default. Higher value = slower protected: public slots: void setCurrentTime(QString currentTime); void currentTimeTimerTimeout(); void setRollAngle(float rollAngle); void setRollRate(float rollRate); void setStartingAngle(float startingAngle); void setStoredStartingAngle(float storedStartingAngle); void setDwellLength(int dwellLength); void setRollDirection(int rollDirection); void setMagnetSpinRate(float magnetSpinRate); void setRotateDirection(float rotateDirection); void setStoredRotateDirection(float storedRotateDirection); void setIsRunning(bool isRunning); void setTimerLength(float timerLength); void setRotateRange(int rotateRange); void setRotateRate(float rotateRate); void setRotateDwell(int newRotateDwell); void setMagnetDirection(bool magnetDirection); void setMainHeight(float newMainHeight); void setStoredMainHeight(float newStoredMainHeight); void setTelescopeLength(float newTelescopeLength); void setStoredTelescopeLength(float newStoredTelescopeLength); void setRunMotors(bool newRunMotors); void setTelescopeDirection(bool newTelescopeDirection); void setMainDirection(bool newMainDirection); void setStartRotate(bool newStartRotate); void setRotateDirectionPrecise(bool newRotateDirectionPrecise); void setLoggedRotate(float newLoggedRotate); void setLoggedRoll(float newLoggedRoll); void setStartAdjustRoll(bool newStartAdjustRoll); void setAdjustDir(bool newAdjustDir); void setStartAdjustSweep(bool newStartAdjustSweep); signals: void currentTimeChanged(QString currentTime); void rollAngleChanged(float rollAngle); void rollRateChanged(float rollRate); void startingAngleChanged(float startingAngle); void storedStartingAngleChanged(float storedStartingAngle); void dwellLengthChanged(int dwellLength); void rollDirectionChanged(int rollDirection); void magnetSpinRateChanged(float magnetSpinRate); void rotateDirectionChanged(float rotateDirection); void storedRotateDirectionChanged(float storedRotateDirection); void isRunningChanged(bool isRunning); void userRequestStop(); void destroyMotorThread(); //void userRequestStart(); void timerLengthChanged(float timerLength); void rotateRangeChanged(); void rotateRateChanged(); void rotateDwellChanged(); void magnetDirectionChanged(bool magnetDirection); void mainHeightChanged(); void storedMainHeightChanged(); void telescopeLengthChanged(); void storedTelescopeLengthChanged(); void runMotorsChanged(); void telescopeDirectionChanged(); void mainDirectionChanged(); void startRotateChanged(); void rotateDirectionPreciseChanged(); void loggedRotateChanged(); void loggedRollChanged(); void startAdjustRollChanged(); void adjustDirChanged(); void startAdjustSweepChanged(); protected: private: QString m_currentTime; QTimer *m_currentTimeTimer; float m_rollAngle; float m_rollRate; float m_startingAngle; int m_dwellLength; int m_rollDirection; float m_magnetSpinRate; float m_rotateDirection; bool m_isRunning; float m_storedStartingAngle; float m_storedRotateDirection; float m_timerLength; int m_rotateRange; float m_rotateRate; int m_rotateDwell; bool m_magnetDirection; float m_mainHeight; float m_storedMainHeight; float m_telescopeLength; float m_storedTelescopeLength; bool m_runMotors; bool m_telescopeDirection; bool m_mainDirection; bool m_startRotate; bool m_rotateDirectionPrecise; float m_loggedRotate; float m_loggedRoll; bool m_startAdjustRoll; bool m_adjustDir; bool m_startAdjustSweep; }; #endif // SYSTEM_H
-
I can't get a signal-slot connection to work
What exactly doesn't work for signal-slot-connections? Which ones don't work and which ones do?
if that is the "proper" way to do that
Have you read the documentation of
QThread
? If you just want to stop the oscillating motion, why don't you this function?Another way would be to emit a signal to the thread.
Working with global variables should work in theory.
I am not sure, why you useextern int
for a flag. Could be astd::atomic_bool
as well.And if by some miracle it's an issue with systemHandler:
What's the miracle and what's the issue?
Generally:
Strip your code down to the bare minimum and see when it starts working. -
I can't get a signal-slot connection to work
What exactly doesn't work for signal-slot-connections? Which ones don't work and which ones do?
if that is the "proper" way to do that
Have you read the documentation of
QThread
? If you just want to stop the oscillating motion, why don't you this function?Another way would be to emit a signal to the thread.
Working with global variables should work in theory.
I am not sure, why you useextern int
for a flag. Could be astd::atomic_bool
as well.And if by some miracle it's an issue with systemHandler:
What's the miracle and what's the issue?
Generally:
Strip your code down to the bare minimum and see when it starts working.@Axel-Spoerl Ah sorry, I should've been more specific. I am trying 2 methods to stop my function. When I use a global variable (stopFlag), I am able to interrupt 1 worker thread that runs the function "controlSpin()". This thread also has a infinite loop that stops when stopFlag == 1. However, when I try and use a global variable (stopAdjustSweepFlag) to stop a worker thread that is running the function "adjustSweep()", it doesn't stop the adjustSweep thread for a reason I can't figure out. I notice that the stopAdjustSweepFlag variable is not updated in the worker thread, but it is updated in the main thread. However, stopFlag is able to stop adjustSweep(), but I'd like to be able to use stopAdjustSweepFlag global var to stop the adjustSweep() function.
Since the global var wasn't working, I attempted to use a signal (from main thread called: threadStopAdjustSweepSignal) to invoke the slot (in worker thread called: stopAdjustSweep()) that should theoretically stop the infinite loop. However, the slot is never called in the worker thread, even though the signal is emitted in the main thread.
Specifically this line in threadController.cpp:QObject::connect(this, &threadController::threadStopAdjustSweepSignal, adjustSweepMotor, &motorController::stopAdjustSweep, Qt::QueuedConnection);
I put miracle because I don't know where the issue is haha. Just included code that might help with diagnosing the problem.
I'll try the atomic bool and the requestInterruption() and see what I get!
-
There is no
stopAdjustSweep
slot in themotorController
class. However, it is being connected and directly invoked. So this code won't even compile. I can seethreadStopAdjustSweepSignal
, but it's not emitted anywhere. The code looks very busy and chaotic, lots of dead code.
Please boil the issue down to a minimal reproducible example, that compiles. This exercise will already help to isolate the issue. -
Hi sorry, I was in the midst of rewriting the code to a simpler example, but decided to try adding Q_INVOKABLE in front of the function that was not working in the .h file. Now it works! Thanks.
-