Tango Controls

Tango Controls

What's happened TANGO?

It is a system for managing various hardware and software.
TANGO currently supports 4 platforms: Linux, Windows NT, Solaris and HP-UX.
Working with Linux (Ubuntu 18.04) will be described here

What is it for?

Simplifies work with various hardware and software.

  • You do not need to think about how to store data in the database, it is already done for you.
  • It is only necessary to describe the mechanism for polling sensors.
  • Reduces all your code to one standard.

Where to get?

From the sources I could not run it, I used the ready-made TangoBox 9.3 image for work.
The instructions describe how to install from packages.

What does it consist of?

  • JIVE - serves to view and edit the TANGO database.
  • POGO β€” code generator for TANGO device servers.
  • Astor β€” program manager for the TANGO system.

We will only be interested in the first two components.

Supported programming languages

  • C
  • C++
  • Java
  • JavaScript
  • Python
  • Matlab
  • LabVIEW

I worked with her in python & c++. Here c++ will be used as an example.

Now let's move on to the description of how to connect the device to TANGO and how to work with it. The fee will be taken as an example. GPS neo-6m-0-001:

Tango Controls

As you can see in the picture, we connect the board to the PC via UART CP2102. Device appears when connected to PC /dev/ttyUSB[0-N], usually /dev/ttyUSB0.

POGO

Now let's run pogo, and with generate the skeleton code to work with our board.

pogo

Tango Controls

I have already created the code, let's create it again File->New.

Tango Controls

We get the following:

Tango Controls

Our device (under the device in the future we will mean the software part) is empty and has two control commands: State & Status.

It must be filled with the necessary attributes:

Device Property - default values ​​​​that we pass to the device to initialize it, for the GPS board, you need to transfer the name of the board in the system com="/dev/ttyUSB0" and com port speed baugrade=9600

Commands - commands to control our device, they can be given arguments and a return value.

  • STATE - returns the current state, from States
  • STATUS - returns the current status, this is a string complement to STATE
  • GPSArray returns gps line in the form DevVarCharArray

Next, the attributes of the device that can be read / written to / from it are set.
Scalar Attributes - simple attributes (char, string, long, etc.)
Spectrum Attributes - one-dimensional arrays
Image Attributes - two-dimensional arrays

States - the state in which our device is located.

  • OPEN β€” the device is open.
  • CLOSE β€” the device is closed.
  • FAILT - error.
  • ON β€” receive data from the device.
  • OFF β€” no data from the device.

An example of adding an attribute gps_string:

Tango Controls

polling period time in ms, how often the value of gps_string will be updated. If the update time is not set, then the attribute will be updated only on request.

Happened:

Tango Controls

Now you need to generate code File->Generate

Tango Controls

By default, the Makefile is not generated, the first time you need to check the box to create it. This is done so that the changes made to it are not deleted during the new generation. Having created it once and configured it for your project (prescribe compilation keys, additional files), you can forget about it.

Now let's move on to programming. pogo generated the following for us:

Tango Controls

We will be interested in NEO6M.cpp & NEO6M.h. Let's take a class constructor as an example:

NEO6M::NEO6M(Tango::DeviceClass *cl, string &s)
 : TANGO_BASE_CLASS(cl, s.c_str())
{
    /*----- PROTECTED REGION ID(NEO6M::constructor_1) ENABLED START -----*/
    init_device();

    /*----- PROTECTED REGION END -----*/    //  NEO6M::constructor_1
}

What is there and what is the main thing here? In the init_device() function, memory is allocated for our attributes: gps_string & gps_array, but it is not important. The most important thing here, these are the comments:

/*----- PROTECTED REGION ID(NEO6M::constructor_1) ENABLED START -----*/
    .......
/*----- PROTECTED REGION END -----*/    //  NEO6M::constructor_1

Everything that is inside this comment block will not be included in subsequent code regenerations in pogo move away!. Everything that is not in blocks will be! These are the places where we can program and make our edits.

Now what are the main functions of the class NEO6M:

void always_executed_hook();
void read_attr_hardware(vector<long> &attr_list);
void read_gps_string(Tango::Attribute &attr);
void read_gps_array(Tango::Attribute &attr);

When we want to read the value of an attribute gps_string, the functions will be called in the following order: always_executed_hook, read_attr_hardware ΠΈ read_gps_string. The read_gps_string will be populated with the gps_string value.

void NEO6M::read_gps_string(Tango::Attribute &attr)
{
    DEBUG_STREAM << "NEO6M::read_gps_string(Tango::Attribute &attr) entering... " << endl;
    /*----- PROTECTED REGION ID(NEO6M::read_gps_string) ENABLED START -----*/
    //  Set the attribute value

        *this->attr_gps_string_read = Tango::string_dup(this->gps.c_str());

    attr.set_value(attr_gps_string_read);

    /*----- PROTECTED REGION END -----*/    //  NEO6M::read_gps_string
}

Compilation

Go to the source folder and:

make

The program will be compiled into the ~/DeviceServers folder.

tango-cs@tangobox:~/DeviceServers$ ls
NEO6M

JIVE

jive

Tango Controls

There are already some devices in the database, now let's create our Edit->Create Server

Tango Controls

Now let's try to connect to it:

Tango Controls

Nothing will come of it, first you need to run our program:

sudo ./NEO6M neo6m -v2

I can connect to the com port only with rights root-but. v - logging level.

Now we can connect:

Tango Controls

Customer

In graphics, looking at pictures is certainly good, but something more useful is needed. Let's write a client that will connect to our device and take readings from it.

#include <tango.h>
using namespace Tango;

int main(int argc, char **argv) {
    try {

        //
        // create a connection to a TANGO device
        //

        DeviceProxy *device = new DeviceProxy("NEO6M/neo6m/1");

        //
        // Ping the device
        //

        device->ping();

        //
        // Execute a command on the device and extract the reply as a string
        //

        vector<Tango::DevUChar> gps_array;

        DeviceData cmd_reply;
        cmd_reply = device->command_inout("GPSArray");
        cmd_reply >> gps_array;

        for (int i = 0; i < gps_array.size(); i++) {            
            printf("%c", gps_array[i]);
        }
        puts("");

        //
        // Read a device attribute (string data type)
        //

        string spr;
        DeviceAttribute att_reply;
        att_reply = device->read_attribute("gps_string");
        att_reply >> spr;
        cout << spr << endl;

        vector<Tango::DevUChar> spr2;
        DeviceAttribute att_reply2;
        att_reply2 = device->read_attribute("gps_array");
        att_reply2.extract_read(spr2);

        for (int i = 0; i < spr2.size(); i++) {
            printf("%c", spr2[i]);
        }

        puts("");

    } catch (DevFailed &e) {
        Except::print_exception(e);
        exit(-1);
    }
}

How to compile:

g++ gps.cpp -I/usr/local/include/tango -I/usr/local/include -I/usr/local/include -std=c++0x -Dlinux -L/usr/local/lib -ltango -lomniDynamic4 -lCOS4 -lomniORB4 -lomnithread -llog4tango -lzmq -ldl -lpthread -lstdc++

Result:

tango-cs@tangobox:~/workspace/c$ ./a.out 
$GPRMC,,V,,,,,,,,,,N*53

$GPRMC,,V,,,,,,,,,,N*53

$GPRMC,,V,,,,,,,,,,N*53

We got the result as the return of the command, taking the attributes of a string and an array of characters.

references

I wrote the article for myself, because after a while I begin to forget how and what to do.

Thank you for attention.

Source: habr.com

Add a comment