How to accomplish a conversion...



  • I have a new toy from Teknic; it is a clear path stepper motor. Their library is free and I have mirrored it at www.briggsassociates.org/src because it is fundamental to my questions. The example therein "SingleThreaded" seems to be the closest to fit my project. I am compiling this on Raspberry Pi 3 with Qt Creator. I have basically moved a copy of Axismain into the Mainwindow.cpp constructor and destructor functions and removed parts that didn't seem to belong. I then did the same with several buttons. My buttons produce limited movement on the stepper, but I think I am doing it the wrong way. So my question becomes "how may I implement a state machine exactly like the one in Axis.cpp (in the example) but in the context of Mainwindow.cpp? This would allow me to manipulate the state machine variables without stopping and starting the state machine. Thanks for any advice...


  • Lifetime Qt Champion

    Hi,

    It's a bit too much to ask people do download some code from somewhere, analyse it and then provide you with a solution.

    From your description, you should check Qt's state machine framework. Don't try to put everything in your main window. Having a dedicated object doing the communication with the motor is way better.



  • I'm not really hopeful for a solution (altho I would be joyful!). I have looked at QStateMachine, but cannot get even the simplest machine to work. I followed another tutorial fairly closely. I did not ever see addition of signals or slots in that tutorial. Changing the code machine->setInitialState(s1); to machine->setInitialState(s2); does change the "initially" displayed label. Button clicks do not work. here is my code:
    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include <QEventTransition>

    MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
    {
    ui->setupUi(this);

    machine = new QStateMachine(this);
    
    s1 = new QState();
    s1->assignProperty(ui->stateLabel, "text", "ON: 1");
    s2 = new QState();
    s2->assignProperty(ui->stateLabel, "text", "OFF: 2");
    
    QEventTransition *t1 = new QEventTransition(ui->ChangeState, QEvent::MouseButtonPress);
    t1->setTargetState(s2);
    QEventTransition *t2 = new QEventTransition(ui->ChangeState, QEvent::MouseButtonPress);
    t2->setTargetState(s1);
    
    machine->addState(s1);
    machine->addState(s2);
    machine->setInitialState(s1);
    machine->start();
    

    }

    MainWindow::~MainWindow()
    {
    delete ui;
    }

    no errors, just does not do what i expected...
    now if I can fix this state machine, would it be too much to ask (in general terms) for help translating the before mentioned state machine into QStateMachine?
    I know nothing about state machines, they seem overly complicated. If there is an easier or simpler way I would gladly abandon the state machine concept. My trouble is that I don't really know any other way that will allow me to change the variables in the Axis class from the Qmainwindow.cpp context.

    You are right about asking for a lot and I am sorry for that.
    Thank you for reading my posts!


  • Lifetime Qt Champion

    What is ui->ChangeState ?



  • I stupidly named a button 'ChangeState'...



  • I rewrote again and have ONE state change that is working...
    enter and leave change the text in a label when you move the mouse over the label.

    nothing I do works when I try to use QEvent MouseButtonPress or MouseButtonRelease.

    I will work on that.

    please look at this code:
    // Start the machine cycling
    while (!m_quitting) {
    try {
    // Save last state for debugging purposes
    m_lastState = m_state;

    		// Check for alerts
    		CheckForAlerts();
    
    		switch (m_state) {
    		case STATE_IDLE:
    			// Update idle state
    			// Quitting?
    			if (m_quitting)
    				continue;
    			m_state = STATE_SEND_MOVE;
    			break;
    		case STATE_SEND_MOVE:
    			// Initiate the motion
    			if (m_moveCount % 2 == 0) {
    				PosnMove(5000);
    			}
    			else {
    				//Set new motion parameters before the next move
    				ChangeMotionParams(1500, 7500, 4,
    					m_node->Info.PositioningResolution.Value() / 4, 95);
    
    				VelMove(50);
    			}
    
    			// Reset our motion parameters.  The parameters for the 
    			// next move could be entered instead to get a head start
    			InitMotionParams();
    
    			m_state = STATE_WAIT_FOR_MOVE_DONE;
    			break;
    		case STATE_WAIT_FOR_MOVE_DONE:
    			//Check if the move is done yet
    			moveDone = WaitForMove(m_moveTimeoutMs);
    			if (!moveDone) {
    				printf("ERROR: [%2d] timed out waiting for move done\n",
    					m_node->Info.Ex.Addr());
    				return;
    			}
    			else {
    				m_moveCount++;
    				m_state = STATE_IDLE;
    			}
    			if (m_moveCount == 4) {
    				// Stop once we've properly demonstrated movement
    				Quit();
    			}
    			PrintStats();
    			if (m_quitting)
    				continue;
    			break;
    		default:
    			fprintf(stderr, "Illegal state");
    			return;
    		}
    	} // Try block
    	catch (mnErr &err) {
    		fprintf(stderr, "Link error: %s\n", err.ErrorMsg);
    		ResetToIdle();
    		continue;
    	}
    	catch (...) {
    		fprintf(stderr, "Node failed generically.\n");
    		ResetToIdle();
    	}
    }
    
    m_state = STATE_EXITED;
    ResetToIdle();
    

    and help me understand it in terms of QStateMachine...

    Thanks



  • I am still having trouble with QStateMachine...
    How may I write my own QEvent or is it better to write my own QTransitionEvent?
    In other words how may I trigger a transition from code after I add it to the machine?
    Or does the machine trigger it's own transitions?

    I am so sorry to ask dumb questions. I will go back to searching... I just need to know what to search on....


  • Lifetime Qt Champion

    The quick and easy start is to put that code in its own thread in ordre to make it run in your application.

    Then you should start by doing some sketches that shows each state and what it should do and where it should go after that. From there you'll be able to start implementing your state machine more easily.



  • By put that code in it's own thread, do you mean adding it to my project?

    I know how to add the #includes, and I finally got the Qt state machine to run like that. does the code machine->start(); start a new thread?


  • Lifetime Qt Champion

    No it doesn't, it needs an event loop running. See the QStateMachine::start documentation.



  • Thank you, I will read that info closely.

    It looks like I can somehow send a signal to the state machine to change it's states. Now comes the challenge for me to have the state machine manipulate the code in the Axis class.

    I can't even manage to do that manually yet, but maybe putting everything inside the state machine loop will allow me to change the Axis->variables from the different states.

    Is there a forum where a very new c++ beginner can ask questions? I hate to keep wasting your time....

    Thanks,


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.