NEWBIE! In over his head (MOTOR CONTROL, pointers, classes and whatnot

Hello All!

My name is Chris, 32, from The Netherlands, and currently im working on a project for my education (Mechanical Engineering) at the company I work at. (I go to school in the evenings).
My project is to create a 3D scanner. My own addition is to only use secondhand materials already available at the company, leftovers so to say. So far so good, I’ve constructed a frame from existing used lineair drives, which are driven by MOONS stepper drive motors.

However, the challenge (for me) is the motor control. I’ve had some basic C training. Most code I can read. However, I’m still a script kiddie, I can't write code.

I’ve been given part of an application that can control one stepper drive, written in C++.
However, from my program I want to control multiple stepper drives at once.
I basically understand how the existing program works. But, my current problem is with classes, and multiple threads.
For the simple solution I could copy existing classes + underlying functions, so that I have control for each motor. But I believe I should be able to control multiple motors from one set of code.
( I hope im making sense, I don’t speak programmer ;) ).

I've read a lot about pointers, classes, shared/weak/and whatnot pointers, arrays, threads etc. but im a bit stuck an im hoping you could give me some 'pointers' (pun intended).

I hope i'm making sense, and the code is clear. And if any of you could help me i would be very grateful!

The code: I've divided it into three parts
1: motortest.cpp : main code
2: MotorbarAmp.cpp : code for the motor control, which creates a thread and in which functions are specified
3: MotorbarAmp.h : Header file in which motor class is specified.

First: the main part of the program in which i call the Motorbar application (with IP) Again, how the hell do i do this when i have multiple IP adresses.
I know its something with shared pointers and make_shared.. but.. how?



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include <iostream>
#include <stdio.h>
#include "MotorbarAmp.h"
#include <sstream>
#include <thread>

using namespace std;

int main(int argc, char * argv[])
{
	string line;
	int                 choice = ' ';
	shared_ptr<MotorbarAmp> mb; <<-- IT'S SOMETHING TO DO WITH THIS
	bool initialized = false;
	//boost::asio::io_service io_service;
	cout << "Motor Control Menu \n";
	cout << "Choose motor to calibrate \n";
	while (choice != 'D') 
	{
		cout << "X for x-axis motor";
		cout << "Y for y-axis motor";
		getline(cin, line);
		choice = line[0];
		switch (choice)
		{
		case 'X':
		{
			if (initialized)
			{
				mb = NULL;
			}
			cout << "Perform initialization!" << endl;
			int ipx[4] = { 200, 51, 2, 12 };
			int ipy[4] = { 200, 51, 2, 1 };
			string ipsx, ipsy;
			cout << "Enter IP adress X or press enter for default (" << ipx[0] << "." << ipx[1] << "." << ipx[2] << "." << ipx[3] << ")" << endl;
			getline(cin, ipsx);
			if (ipsx.length() >= 7)
			{
				ipx[0] = atoi(ipsx.substr(0, ipsx.find('.', 0)).c_str());
				ipsx = ipsx.substr(ipsx.find('.', 0) + 1, 50);
				ipx[1] = atoi(ipsx.substr(0, ipsx.find('.', 0)).c_str());
				ipsx = ipsx.substr(ipsx.find('.', 0) + 1, 50);
				ipx[2] = atoi(ipsx.substr(0, ipsx.find('.', 0)).c_str());
				ipsx = ipsx.substr(ipsx.find('.', 0) + 1, 50);
				ipx[3] = atoi(ipsx.c_str());
			}
			uint32_t ip;
			ip = (ipx[0] << 24) | (ipx[1] << 16) | (ipx[2] << 8) | ipx[3];
			cout << "ip = " << ((ip & 0xff000000) >> 24) << "." << ((ip & 0xff0000) >> 16) << "." << ((ip & 0xff00) >> 8) << "." << (ip & 0xff) << endl;
			mb = make_shared<MotorbarAmp>(ip); // <<--AND THIS PART RIGHT HERE
			initialized = true;
			break;
		} 


Second:
the header in which a thread is created for motor control. (problem im facing is multiple IP's. The uint32_t ip part. I think i can do something with an array ?? perhaps a for loop.. but HOW.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include "MotorbarAmp.h"
#include <time.h>
#include "AmpMotor.h"
#include <iostream>
#include <thread>
#include "boost/asio.hpp"

std::thread* worker_thread_asio; <<-- I HAVE TO DO SOMETHING WITH THIS I THINK
bool running = false;
fd_set rfds, wfds, efds;
std::shared_ptr<IMotorBar> amp_motor_; <<- AND ALSO THIS FOR MULTIPLE MOTORS

MotorbarAmp::MotorbarAmp(uint32_t ip) BUT WHAT ABOUT THE IP PART? CAN I SOMEHOW USE MULTIPLE IP's?)BECAUSE EVERY FUNCTION IN THIS FILE USES amp_motor_
{
		amp_motor_ = std::make_shared<AmpMotor>(io_service);
		amp_motor_->SetCallback(this);
		running = true;
		amp_motor_->Setup(true, ip);
		worker_thread_asio = new std::thread(&MotorbarAmp::WorkerAsio, this);
}

void MotorbarAmp::Calibrate() 
{
	amp_motor_->Calibrate();
}

void MotorbarAmp::WorkerAsio() 
{
	try 
	{
		io_service.run();
	}
	catch (boost::system::system_error err)
	{
		cout << err.what();
	}
	cout << "asio thread ended" << endl;
} 



And third: the header file in which the MotorbarAmp class is specified.
Also here, the uint32_t ip part.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#pragma once
#include <stdint.h>
#include <stdio.h>
#include <boost/asio.hpp>
#include "imotorbar.h"

using namespace std;

class MotorbarAmp :
  public std::enable_shared_from_this<MotorbarAmp>,
  public IMotorBarCallback {
private:
  boost::asio::io_service io_service;
  std::vector<MotorErrors> errors;
public:
	MotorbarAmp(uint32_t ip);<<- AGAIN WITH THE IP!//boost::asio::io_service &io_service
  void Calibrate();
  void Stop();
  void WorkerAsio();
  ~MotorbarAmp();
  void SetPosition(int position, int speed);
  void ResetErrors();

  // Inherited via IMotorBarCallback
  virtual void Initialized() override;
  virtual void Calibrated(int max_pos_in_um) override;
  virtual void ConnectionEstablished() override;
  virtual void ConnectionClosed() override;
  virtual void PositionUpdate(int position_in_um, bool moving) override;
  virtual void Error(MotorErrors error, bool set) override;
};
Have a vector of type MotorbarAmp.
Ok, a vector. So far so good.

so, something like?
 
vector<MotorbarAmp> mb;


Basically, what i want to achieve is that i have three instances of motorbarAmp running at the same time. so that i can control the functions within motorbaramp.

So eventually is i would control them i could use

1
2
mb1->Calibrate();
mb2->Stop();



But within my main program, im having problems with the uint32_t ip part.

How would i use a vector for that ?
yes like this.

Here are the steps I would do.

1. Declare a vector(which you have done). vector<MotorbarAmp> mb;
2. Ask how many motors would the user like to create.
3. Loop that many times, asking the user to enter the IP with all the validation code.
4. Then add a new MotorbarAmp to the vector passing the IP with each iteration of the loop.

You can refer to each motor like this mb(1), mb(2) or use a variable if you want to control them all with one loop. like this

1
2
3
for (int i = 0; i < NumOfMotors; i++) {
    mb(i)->Stop();
}


Thanks, for the input and help.

I'm going to try this today.

THe vector doesn't work (or more probably; im doing it wrong).

When i used a vector, and iteration I could use the functions of the class. But not start three threads of the same class with their own identifier running.

So, eventually i would stop all three motors and have to give mb1->Stop(); mb2->Stop();mb3->Stop.

But, to do that i first need to initialize and make contact with the motors, which is done by the mb = make_shared<MotorbarAmp>(ip) part

so basically what i want is something like this.
I know the mb(i) doesnt work after the shared pointer.
This is to illustrate what im thinking about.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <iostream>
#include <stdio.h>
#include "MotorbarAmp.h"
#include <sstream>
#include <thread>

using namespace std;

int main(int argc, char * argv[])
{
	string line;
	int                 choice = ' ';
	std::shared_ptr<MotorbarAmp> mb(i);
	bool initialized = false;
	cout << "How many motors? " << endl;
	string NumOfMotors;
	getline(cin, NumOfMotors);
	int MotNr = atoi(NumOfMotors.c_str());
	for (int i = 0; i < MotNR; i++)
    {
			int ipp[4] = { 200, 51, 254, 5 };
			string ips;
			cout << "enter IP address, or press enter to accept default (" << ipp[0] << "." << ipp[1] << "." << ipp[2] << "." << ipp[3] << ")" << endl;
			getline(cin, ips);
			if (ips.length() >= 7)
			{
				ipp[0] = atoi(ips.substr(0, ips.find('.', 0)).c_str());
				ips = ips.substr(ips.find('.', 0) + 1, 50);
				ipp[1] = atoi(ips.substr(0, ips.find('.', 0)).c_str());
				ips = ips.substr(ips.find('.', 0) + 1, 50);
				ipp[2] = atoi(ips.substr(0, ips.find('.', 0)).c_str());
				ips = ips.substr(ips.find('.', 0) + 1, 50);
				ipp[3] = atoi(ips.c_str());
			}
			uint32_t ip;
			ip = (ipp[0] << 24) | (ipp[1] << 16) | (ipp[2] << 8) | ipp[3];
			cout << "ip = " << ((ip & 0xff000000) >> 24) << "." << ((ip & 0xff0000) >> 16) << "." << ((ip & 0xff00) >> 8) << "." << (ip & 0xff) << endl;
			mb(i); = make_shared<MotorbarAmp>(ip); //<<<- I NEED THIS TO CREATE THREE instances running of <MotorbarAmp>
			bool initialized = true;
			return(0);
		}
		//mb = make_shared<MotorbarAmp>(ip);
		//bool initialized = true;
	}


so, what am I doing wrong here ?
Ok,

I have something working now, i used an if function (not elegant, but practical)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#include <iostream>
#include <stdio.h>
#include "MotorbarAmp.h"
#include <sstream>

using namespace std;

int main(int argc, char * argv[])
{
	std::shared_ptr<MotorbarAmp> mb1;
	std::shared_ptr<MotorbarAmp> mb2;
	std::shared_ptr<MotorbarAmp> mb3;
	bool initialized = false;
	string line;
	int					choice = ' ';

	cout << "Welcome to the motor control menu \n" << endl;
	cout << "----------------------------------\n" << endl;
	cout << "How many motors? " << endl;
	string NumOfMotors;
	getline(cin, NumOfMotors);
	int MotNr = atoi(NumOfMotors.c_str());
	while (choice != 'Q')
	{
		cout << "What would you like to do ? \n" << endl;
		getline(cin, line);
		choice = line[0];
		switch (choice)
		{
		case 'i':
		{
			cout << "Initialization1 \n" << endl;
			for (int i = 0; i < MotNr; i++)
			{
				if (i < 1)
				{
					//std::shared_ptr<MotorbarAmp> mb1;
					bool initialized = false;
					if (initialized)
					{
						mb1 = NULL;
					}
					int ipp[4] = { 200, 51, 254, 5 };
					string ips;
					cout << "enter IP address, or press enter to accept default (" << ipp[0] << "." << ipp[1] << "." << ipp[2] << "." << ipp[3] << ")" << endl;
					getline(cin, ips);
					if (ips.length() >= 7)
					{
						ipp[0] = atoi(ips.substr(0, ips.find('.', 0)).c_str());
						ips = ips.substr(ips.find('.', 0) + 1, 50);
						ipp[1] = atoi(ips.substr(0, ips.find('.', 0)).c_str());
						ips = ips.substr(ips.find('.', 0) + 1, 50);
						ipp[2] = atoi(ips.substr(0, ips.find('.', 0)).c_str());
						ips = ips.substr(ips.find('.', 0) + 1, 50);
						ipp[3] = atoi(ips.c_str());
					}
					uint32_t ip;
					ip = (ipp[0] << 24) | (ipp[1] << 16) | (ipp[2] << 8) | ipp[3];
					cout << "ip = " << ((ip & 0xff000000) >> 24) << "." << ((ip & 0xff0000) >> 16) << "." << ((ip & 0xff00) >> 8) << "." << (ip & 0xff) << endl;
					mb1 = make_shared<MotorbarAmp>(ip);
					initialized = true;
				}
				else if (0 > i < 2)
				{
					//std::shared_ptr<MotorbarAmp> mb2;
					bool initialized = false;
					if (initialized)
					{
						mb2 = NULL;
					}
					int ipp[4] = { 200, 51, 254, 5 };
					string ips;
					cout << "enter IP address, or press enter to accept default (" << ipp[0] << "." << ipp[1] << "." << ipp[2] << "." << ipp[3] << ")" << endl;
					getline(cin, ips);
					if (ips.length() >= 7)
					{
						ipp[0] = atoi(ips.substr(0, ips.find('.', 0)).c_str());
						ips = ips.substr(ips.find('.', 0) + 1, 50);
						ipp[1] = atoi(ips.substr(0, ips.find('.', 0)).c_str());
						ips = ips.substr(ips.find('.', 0) + 1, 50);
						ipp[2] = atoi(ips.substr(0, ips.find('.', 0)).c_str());
						ips = ips.substr(ips.find('.', 0) + 1, 50);
						ipp[3] = atoi(ips.c_str());
					}
					uint32_t ip;
					ip = (ipp[0] << 24) | (ipp[1] << 16) | (ipp[2] << 8) | ipp[3];
					cout << "ip = " << ((ip & 0xff000000) >> 24) << "." << ((ip & 0xff0000) >> 16) << "." << ((ip & 0xff00) >> 8) << "." << (ip & 0xff) << endl;
					mb2 = make_shared<MotorbarAmp>(ip);
					initialized = true;
				}
				else if (1 < i < MotNr)
				{
					//std::shared_ptr<MotorbarAmp> mb3;
					bool initialized = false;
					if (initialized)
					{
						mb3 = NULL;
					}
					int ipp[4] = { 200, 51, 254, 5 };
					string ips;
					cout << "enter IP address, or press enter to accept default (" << ipp[0] << "." << ipp[1] << "." << ipp[2] << "." << ipp[3] << ")" << endl;
					getline(cin, ips);
					if (ips.length() >= 7)
					{
						ipp[0] = atoi(ips.substr(0, ips.find('.', 0)).c_str());
						ips = ips.substr(ips.find('.', 0) + 1, 50);
						ipp[1] = atoi(ips.substr(0, ips.find('.', 0)).c_str());
						ips = ips.substr(ips.find('.', 0) + 1, 50);
						ipp[2] = atoi(ips.substr(0, ips.find('.', 0)).c_str());
						ips = ips.substr(ips.find('.', 0) + 1, 50);
						ipp[3] = atoi(ips.c_str());
					}
					uint32_t ip;
					ip = (ipp[0] << 24) | (ipp[1] << 16) | (ipp[2] << 8) | ipp[3];
					cout << "ip = " << ((ip & 0xff000000) >> 24) << "." << ((ip & 0xff0000) >> 16) << "." << ((ip & 0xff00) >> 8) << "." << (ip & 0xff) << endl;
					mb3 = make_shared<MotorbarAmp>(ip); //<<<- I NEED THIS TO CREATE THREE instances running of <MotorbarAmp>
					initialized = true;
				}

			}
		}
		case 'C':
		{
			cout << "Which motor do you want to calibrate? \n" << endl;
			//cin >> q;
			if (initialized)
			{
				cout << "Performing calibration \n" << endl;
				mb1->Calibrate();
			}
			else
			{
				cout << "Motor bar not initialized yet \n" << endl;
			}
			break;
		}

		return(0);
		}

	}
}


However, now i've g ot a problem with my asio_threads.

Output, when i enter my second IP adress: Asio Thread Ended.
So, there's something going on with this part:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include "MotorbarAmp.h"
#include <time.h>
#include "AmpMotor.h"
#include <iostream>

#include <thread>
#include "boost/asio.hpp"

std::thread* worker_thread_asio;

bool running = false;
fd_set rfds, wfds, efds;
std::shared_ptr<IMotorBar> amp_motor_;

MotorbarAmp::MotorbarAmp(uint32_t ip) 
{
		cout << "test4" << endl;
		amp_motor_ = std::make_shared<AmpMotor>;
		amp_motor_->SetCallback(this);
		running = true;
		amp_motor_->Setup(true, ip);
		worker_thread_asio = new std::thread(&MotorbarAmp::WorkerAsio, this);
		cout << "test5" << endl;
	
}


So, somehow i can make instances of the shared pointer, but i dont create new threads?
Last edited on
Topic archived. No new replies allowed.