📜 ⬆️ ⬇️

MRAA library for working with Intel Edison and Intel Galileo boards

This article describes the MRAA library, which can greatly simplify working with various types of devices that use:




Instead of examples with complete programs, we will consider small fragments in the C language, which will show the basic principles of the MRAA API. To get more information from this article, you should know the following things:


This article does not explain how to compile, build a program, and install applications on this platform.
')

1. Overview MRAA


MRAA (pronounced "em-ra") is a low-level library written in C. It is designed to abstract from the details associated with accessing and controlling I / O on a platform such as Intel Galileo or Intel Edison, by introducing one small API .


1.1 Downloading the MRAA Library and API Documentation


The MRAA package is already installed on Intel Galileo and Intel Edison and can be connected to your code as shown below. You can also download the latest source code from the Intel repository.
API documentation is available at http://iotdk.intel.com/docs/master/mraa/

1.2 GPIO pin names


There are various “pins” in this article. The hardware pins are usually referred to by number. The pin number can also begin with the letter “D” for the digital type and the letter “A” for the analog type. For example, “D0” will point to digital pin # 0, and “A3” on analog input pin # 3. Pin can also be specified as GPIO6, i.e. This is GPIO-pin number 6, without specifying its type “D” or “A”, i.e. It can be both digital and analog.

1.3 Library Linking


When compiling, link the library with the command –lmraa, for example:

gcc -g blink.c -o blink -lmraa 

1.4 Using MRAA


Before writing code, remember the following.

1. At the beginning of the program, the MRAA should be initialized as follows:

 mraa_result_t rv; rv = mraa_init(); if (rv != MRAA_SUCCESS)    . . . 

2. Many MRAA functions return a result of type mraa_result_t. It is very important to make sure that the function call occurred without errors.

3. The examples in this article do not perform error checking, but it is still highly recommended to do this.

4. After initialization, you must specify the MRAA, which way you want to use the pin (input / output, digital / analog / PWM / AURT). Below will be shown how to do it.

5. When the work is completed (for example, at the end of the program), MRAA must be released to release the pins occupied so that it resets all internal states and settings. Below will be shown how to do it.

1.5 Connecting MRAA Header Files


The main MRAA include file is mraa.h. It connects with other hardware-dependent header files. For example:
The code for an analog device should include:

 #include <mraa.h> #include <mraa/aio.h> 

The code for a digital device should include:

 #include <mraa.h> #include <mraa/gpio.h> 

2. Using MRAA with analog devices


An analog device is a device that receives data by measuring the pin voltage value, varying from 0 to the maximum supported. This maximum voltage is called the reference voltage (AREF - Analog Reference Voltage). For example, an analog pressure sensor can provide a voltage value starting at 0 (corresponding to no pressure), and increasing with increasing pressure. This voltage on the sensor is converted into a number by a device called an ADC (Analog-to-digital converter, ADC - analog-to-digital converter). The program that works with the sensor reads this number, issued from the ADC.

2.1 Reference Voltage


The reference voltage is usually 3.3 V or 5.0 V DC. However, the reference voltage may differ, as some platforms, such as Intel Edison, allow you to set a different reference value instead of using the built-in value. Therefore, you need to know the exact value of the reference voltage before you receive data from the device.

2.2 bit ADC


The ADC resolution is very important, as it determines the accuracy of your measurements. All ADCs used on the Intel platform are 10 bits wide (1024 values). And at least in the case of Intel Edison 12 bits (4096 values).

You can determine the approximate step of voltage measurement accuracy by dividing the value of the reference voltage by the number of available values. This value can then be used in the application. For example, with a reference voltage of 5 V and a bit width of 10 bits, we find that the ADC step is approximately 5 mV. Since 5.0 / 1024 = 0.00488 V

2.3 Interpretation of data


Using the previously described information, you can determine the approximate voltage that is on the analog pin. With a higher ADC resolution, it is possible to measure voltage with greater accuracy.

2.4 Analog Example


Grove's humidity sensor is an example of a simple analog device. It is simply a resistor that changes the voltage level at the analog input according to which moisture level was determined. The following example shows how the sensor works when it is connected to pin A0. The program shows how to initialize MRAA and pin A0, read the value, print it and then release the pin.

 int main() { /* initialize MRAA */ mraa_init(); /* create an MRAA analog context */ mraa_aio_context m_aio; /* initialize A0 for use as an analog input */ m_aio = mraa_aio_init(0); /* read the value, an integer */ int value; value = mraa_aio_read(m_aio); /* print the value */ printf(“The value returned was: %d\n”, value); /* now release (close) the pin and exit */ mraa_aio_close(m_aio); return(0) ; } 

With an ADC of 10 bits, the return value will be from 0 to 1023. How to interpret the value depends on the sensor device. For the Grove sensor and the ADC bit depth of 10 bits, the documentation gives the following ranges for the state of dry, wet and damp.


It is important to remember that all sensors are different, and their values ​​can be difficult to decode. Consider the following:

1. Some sensors have jitter (jitter). In this case, you need to obtain several consecutive values ​​from the sensor and find the average value.

2. If you are writing a MRAA driver for use on different platforms, it is important that you correctly specify the reference voltage and resolution of the ADC that will be used in the calculations. Otherwise, the resulting data may be useless. In the previous example, we did not need to know the reference voltage, but this does not apply to other more complex analog devices. On some devices, the exact value of the reference voltage and the resolution of the ADC are required to determine the value received from the sensor.

3. The value on the sensor is not always linearly related to the measured parameter. In this case, you need to look in the documentation for the formulas for the translation of values ​​or use additional libraries, for example, UPM.

3. Using MRAA with digital devices


Digital devices deal with high and low signal values. Only these two values ​​are used. For example, in a system operating at a voltage of 5 V, a low level may correspond to 0 V, and a high level of 5 V. Usually a high level is indicated by 1 and a low level by 0.
Digital devices can be configured for input and output. To be used as an input device, you need to use MRAA to read from a digital pin and return a value indicating whether the voltage was high or low.

MRAA provides an API for reading and writing the status of a digital pin. Additionally, you can connect an interrupt handler to a digital input. To use the digital input and output capabilities in MRAA, you need to include a header file.

 #include <mraa/gpio.h> 

3.1 Example of using a digital input


For example, take a simple digital device, a button. When the button is not pressed, it has a high voltage, when pressed it is low.

 int main() { /* initialize MRAA */ mraa_init(); /* create an MRAA digital context */ mraa_ai o_context m_aio; /* initialize D2 for use as a digital pin */ m_gpio = mraa_gpio_init(2); /* configure the digital pin as an input */ mraa_gpio_dir(m_gpio, MRAA_GPIO_IN); /* read the value into an integer */ int value = mraa_gpio_read(m_gpio); /* print the value */ if (value != 0) printf(“The button is being pushed\n”); else printf(“The button is not being pushed\n”); /* now release (close) the pin and exit */ mraa_gpio_close(m_gpio); return(0); } 

As you can see, everything is quite simple. Notice how we tell MRAA to set the pin to enter using the mraa_gpio_dir () function. Digital pins can be used for both input and output, as opposed to analog pins, which can only work on input.

3.2. Interrupt handlers


Sometimes you do not want to repeat reading the value on the pin to determine the change in its state. Take for example the sensor that is connected to the motor to count the revolutions per minute. In this case, it would be unwise to constantly keep reading the state of a pin to determine changes.

MRAA offers the possibility to create an interrupt handler and connect it with a pin. In this case, the MRAA guarantees that your function will be called whenever a specified state change occurs (from 0 to 1 or from 1 to 0).

Using this feature, it is easy to write the counting function, and tell MRAA to call it when the state changes. Below is a simple example of counting the number of transitions from a high signal state to a low one.

 /* first, create our counting variable */ volatile int counter = 0; /* Now our simple counting function. */ /* This will be our interrupt handler. */ void intrHandler(void *arg) { counter++; } /* now in our main() function */ int main() { /* initialize MRAA */ mraa_init(); /* create an MRAA digital context */ mraa_aio_context m_aio; /* initialize D2 for use as digital pin */ m_gpio = mraa_gpio_init(2); /* configure the digital pin as an input */ mraa_gpio_dir(m_gpio, MRAA_GPIO_IN); /* now, setup an interrupt handler. */ /* Our function (intrHandler()) above will */ /* be called whenever the pin goes from */ /* HIGH to LOW */ */ mraa_gpio_isr(m_gpio, MRAA_GPIO_EDGE_FALLING, intrHandler, NULL); /* sleep for 5 seconds, and then print out the current */ /* value of counter */ sleep(5); printf(“Counter = %d\n”, counter); /* now, stop the interrupt handler and cleanup */ mraa_gpio_isr_exit(m_gpio); /* now release (close) the pin and exit */ mraa_gpio_close(m_gpio); return(0); } 

Note the following in this example:


3.3 Example of digital output


Using digital output is easy. The following example changes the signal from high (1) to low (0) on a digital output with a period of 1 second. Something similar can be used to blink an LED connected to a pin.

 int main() { /* initialize MRAA */ mraa_init(); /* create an MRAA digital context */ mraa_aio_context m_aio; /* initialize D13 for use as a digital pin */ m_gpio = mraa_gpio_init(13); /* configure the digital pin as an output */ mraa_gpio_dir(m_gpio, MRAA_GPIO_OUT); /* now run in a loop 10 times, blinking the output each second */ int i; for (i=0; i<10; i++) { /* turn output on (HIGH) */ mraa_gpio_write(m_gpio, 1); sleep(1); /* turn output off (LOW) */ mraa_gpio_write(m_gpio, 0); sleep(1); } /* now release (close) the pin and exit */ mraa_gpio_close(m_gpio); return(0); } 

As you can see, with MRAA it is very simple to use digital I / O. Interrupt handling is a bit more complicated, but the main thing here is to carefully use the volatile keyword for variables that you work with outside of the interrupt.

4. Using MRAA for Pulse Width Modulation (PWM)


Pulse width modulation (PWM, PWM - Pulse-width modulation) is a type of digital output. PWM is defined by two parameters, the period and the fill factor:


For example, if you set the period to 2 ms, and the fill factor is 50%, then you will receive repeated changes: 1 ms the signal will be high and 1 ms low. Changing the fill factor can be used for various functions, such as controlling the brightness of the LED or the speed of rotation of the motor.

4.1 Basic Terms of Use



 #include <mraa/pwm.h> 

4.2. An example of working with PWM


In the following example, we will change the brightness of the LED. We will do this by setting a period of 10 ms and will increase and decrease the fill factor every 100 ms.

 int main() { /* initialize MRAA */ mraa_init(); /* create an MRAA PWM context */ mraa_pwm_context m_pwm; /* initialize D3 for use as a digital pin */ m_pwm = mraa_gpio_init(3); /* set the period to 10ms */ mraa_pwm_period_ms(m_pwm, 10); /* set the initial duty cycle to 0 */ mraa_pwm_write(m_pwm, 0.0); /* enable PWM output */ mraa_pwm_enable(m_pwm, 1); /* now run in a loop 10 times, dimming or brightening /* /* the LED every 100ms */ int i; float duty = 0.0; for (i=0; i<10; i++) { /* first, start at 0% duty cycle and increase to 100% */ for (duty= 0.0; duty < 1.0; duty+=0.1) { mraa_pwm_write(m_pwm, duty); usleep(100000); } sleep(1); /* now decrease it to 0% */ for (duty= 1.0; duty > 0.0; duty-=0.1) { mraa_pwm_write(m_pwm, duty); usleep(100000); } sleep(1); } /* disable PWM output and clean up */ mraa_pwm_enable(m_pwm, 0); mraa_pwm_close(m_pwm); return(0); } 

Note the following in this example:


5. Using MRAA with Inter-Integrated Circuits (I2C)


Using I2C, remember the following:


 #include <mraa/i2c.h> 

5.1 Example of working with I2C


In the following example, we will work with I2C real time clock (DS1307) and read the value from the register of seconds. We set the I2C MRAA context on the I2C-bus 0, using the address 0x68, and read the second register. The resulting value will be printed every 10 seconds.

It is important to remember that many I2C devices have different requirements, for example, how data should be written or read. Therefore, the details of the work check in the documentation

 int main() { /* initialize MRAA */ mraa_init(); /* create an MRAA I2C context */ mraa_i2c_context m_i2c; /* initialize I2C on bus 0 */ m_i2c = mraa_i2c_init(0); /* now run in a loop 10 times, reading the seconds */ /* register and printing it.*/ int i; for (i=0; i<10; i++) { char buf; /* always specify the address */ mraa_i2c_address(m_i2c, 0x68); /* read in 1 byte. mraa_i2c_read() always reads */ /* starting at register 0x00 */ mraa_i2c_read(m_i2c, &buf, 1); printf(“The seconds returned was: %d\n”, buf); sleep(1); } mraa_i2c_stop(m_pwm); return(0); } 

See the example above:


6. Using MRAA with Universal Asynchronous Receivers / Transmitters (UART)



 #include <mraa/uart.h> 

6.1 UART example


In the following example, we use a fictional UART-based sensor connected to D0 and D1. It will be denoted by UART 0.

It is important that after opening the device the settings that were made automatically by the Linux kernel are correctly changed. We added a setupTTY () function that performs these actions after opening a TTY device.

 int setupTTY(int fd, speed_t baud) { if (fd < 0) return 0; struct termios termio; /* get current modes */ tcgetattr(fd, &termio); /* setup for a 'raw' mode. 8bit, 1 stop bit, no parity, */ /* no echo or special character handling, */ /* no flow control or line editing semantics. */ cfmakeraw(&termio); // set our baud rates cfsetispeed(&termio, baud); cfsetospeed(&termio, baud); // make it so if (tcsetattr(fd, TCSAFLUSH, &termio) < 0) { fprintf(stderr, “%s\n”, “tcsetattr failed”); return 0; } return 1; } /* now our main function */ int main() { /* initialize MRAA */ mraa_init(); /* create an MRAA UART context */ mraa_uart_context m_uart; /* initialize UART 0 (pins D0 and D1 used for TX and RX) */ m_uart = mraa_uart_init(0); /* now that we have our context, query MRAA */ /* to get the file name of the TTY device we need to open. */ char *devPath = mraa_uart_get_dev_path(m_uart); /* if this fails, we can go no further */ if (!devPath) { fprintf(stderr, “%s\n”, “Could not get device path”); return 0; } /* now that we have a device path, open it and set it up */ int fd; if ((fd = open(devPath, O_RDWR)) == -1) { fprintf(stderr, “%s\n”, “Could not open device path”); return 0; } /* now we are almost ready, call setupTTY() and from then on */ /* we can read/write to the device normally. */ /* We assume a baud rate of 9600/ */ if (!setupTTY(fd, B9600)) { fprintf(stderr, “%s\n”, “Could not setup TTY port”); return 0; } /* now we can use standard read and write calls */ /* read(fd, ...) or write(fd, …) */ /* when we are done, close the device and exit */ close(fd); return(0); } 

:


7.


MRAA - Intel Galileo Intel Edison. , MRAA , , , I2C UART . .

Source: https://habr.com/ru/post/368079/


All Articles