Expresate

Si además quieres enviarnos un Artículo para el Blog y redes sociales, pulsa el siguiente botón:

Avisos
Vaciar todo

GPIO de la raspberry lentisimo

6 Respuestas
2 Usuarios
0 Reactions
10.8 K Visitas
fusion
Respuestas: 391
Topic starter
(@fusion)
Ardero
Registrado: hace 18 años

He hecho el siguiente programa y lo he cargado en la raspberry, empleando para cronometrar la libreria chrono de C++11

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h> //read, write, close, usleep
#include <fcntl.h> //constantes: O_RDWR, O_NOCTTY
#include <termios.h> //rs232
#include <time.h>
#include <chrono>
#include "mmapGpio.h"//gpio OJO!!! modificar base address 0x20 a 0x3F para raspberry2
#include "mmapGpio.cpp"//gpio

mmapGpio rpiGpio1; // instantiate an instance of the mmapGpio class

//20*10/9600=20.83ms
void delay_ms(long int ms) { timespec t1,t2;t1.tv_sec=0;t1.tv_nsec=ms*1000*1000; nanosleep(&t1,&t2); }
void delay_us(long int us) { timespec t1,t2;t1.tv_sec=0;t1.tv_nsec=us*1000; nanosleep(&t1,&t2); }
void delay_mbps(long int mbps) {timespec t1,t2;t1.tv_sec=0;t1.tv_nsec=mbps*(500000000L/BAUDRATE); nanosleep(&t1,&t2); }//cambio #V023

//configura gpio outputs e inputs:
void init_gpio();
//Lee estado del puerto de entrada
int lee_puerto(int puerto) { if (rpiGpio1.readPin(puerto) == mmapGpio::HIGH) return 1;else return 0;}
void pone_puerto(int puerto,int estado) { if (estado) rpiGpio1.writePinHigh(puerto );else rpiGpio1.writePinLow( puerto );}

using namespace std;
using namespace std::chrono;

class halla_tiempo_c
{
public:
high_resolution_clock::time_point t1,t2;
void inicia() { t1= high_resolution_clock::now(); }
double halla_tiempo() //retorna el tiempo en segundos
{
t2= high_resolution_clock::now();
duration<double> time_span = duration_cast<duration<double>>(t2 - t1);
return time_span.count();
}
};

int main()
{
halla_tiempo_c tiempo1;
printf("===inicio prueba de reloj cronometrando 50 segundos, dar a entern");getchar();
tiempo1.inicia();
while (tiempo1.halla_tiempo()<50);
printf("===fin prueba de reloj cronometrando 50 segundos===============n");

pone_puerto(3,0);delay_ms(1);
printf("nInicializo y compruebo GPIOs:n");
init_gpio();
int uart_str;
printf("nInicializo y compruebo RS232:n");
rs232_setup(uart_str);
if (uart_str == -1) return -1;
long i,maxi=10000000L,j=0;
tiempo1.inicia();
for (i=0;i<maxi;i++)
{
pone_puerto(3,1);
while( lee_puerto(2)!=1) j++;
pone_puerto(3,0);
while( lee_puerto(2)!=0) j++;
}
double t2=tiempo1.halla_tiempo();
double frecuencia;
frecuencia=1.0*maxi/t2/1.0e6;
printf("nTiempo=%lg Frecuencia=%lg Mhzn",t2,frecuencia);
return 1;
}

void init_gpio()
{
//inputs:
rpiGpio1.setPinDir( 2,mmapGpio::INPUT);
//outputs:
rpiGpio1.setPinDir( 3,mmapGpio::OUTPUT);
}

Entonces he puenteado la GPIO02 con la GPIO03 y segun mi programa pongo un 1 y un 0 a una frecuencia de 2.57Mhz

He usado para ello la libreria mmapGpio

¿Teneis alguna manera de hacerlo más rapido?

Responder
5 respuestas
fusion
Respuestas: 391
Topic starter
(@fusion)
Ardero
Registrado: hace 18 años

Por lo que he visto la culpa es de lo lenta que es leyendo del puerto, escribe a razon de 18.56 megamuestras por segundo pero lee a 6.63megamuestras.
No he usado overclocking

Responder
heli
Respuestas: 748
 Heli
(@heli)
Ardero
Registrado: hace 19 años

Acceder al hardware a través de librerías de alto nivel suele tener ese resultado, demasiadas capas de abstracción hacen que se ralentice todo mucho.

Prueba a usar la librería "bcm2835" que es de bajo-bajo nivel a ver si mejora...

bcm2835_init
bcm2835_gpio_write

Responder
fusion
Respuestas: 391
Topic starter
(@fusion)
Ardero
Registrado: hace 18 años

Hecho y el resultado es:

Usando mmapGpio:
Read : 6.61Mhz
Write: 18.81Mhz

Usando bcm2835:
Read: 6.0Mhz
Write: 11.2-11.5Mhz

Además las mmapGpio al ser compiladas en vez de instaladas son mas fáciles de usar 🙂

El codigo:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <chrono>
#include <bcm2835.h>

//Compile and link flags at geany:
//g++ -pthread -std=c++11 -o3 -Wall -c "%f"
//g++ -pthread -std=c++11 -Wall -o "%e" "%f" -lbcm2835

//configura gpio outputs e inputs:
void init_gpio();
//Lee estado del puerto de entrada
int lee_puerto(uint8_t puerto) { return bcm2835_gpio_lev(puerto);}
void pone_puerto(uint8_t puerto,uint8_t estado) { bcm2835_gpio_write(puerto, estado);}

using namespace std;
using namespace std::chrono;

class halla_tiempo_c
{
public:
high_resolution_clock::time_point t1,t2;
void inicia() { t1= high_resolution_clock::now(); }
double halla_tiempo() //retorna el tiempo en segundos
{
t2= high_resolution_clock::now();
duration<double> time_span = duration_cast<duration<double>>(t2 - t1);
return time_span.count();
}
};

int main()
{
halla_tiempo_c tiempo1;
printf("nInicializo y compruebo GPIOs:n");
init_gpio();
printf("Signal 3 a 0:n");
pone_puerto(RPI_BPLUS_GPIO_J8_05,0);delay_ms(1);
int uart_str;
printf("nInicializo y compruebo RS232:n");
rs232_setup(uart_str);
if (uart_str == -1) return -1;
long i,maxi=10000000L,j=0;
tiempo1.inicia();
for (i=0;i<maxi;i++)
{
// j=lee_puerto(2);
// j+=lee_puerto(2);
pone_puerto(3,1);
pone_puerto(3,0);
}
double t2=tiempo1.halla_tiempo();
double frecuencia;
frecuencia=2.0*maxi/t2/1.0e6;
printf("nTiempo=%lg Frecuencia=%lg Mhzn",t2,frecuencia);
j=0;
pone_puerto(3,1);
j=lee_puerto(2);
// while( lee_puerto(2)!=1) j++;
printf("j=%lin",j);

return 1;
}

void init_gpio()
{
printf("bcm2835_init():n");
bcm2835_init();
printf("gpio02 input:n");
//GPIO2 inputs:
bcm2835_gpio_fsel( 2, BCM2835_GPIO_FSEL_INPT); //RPI_BPLUS_GPIO_J8_03 = GPIO2
//GPIO03 outputs:
printf("gpio03 output:n");
bcm2835_gpio_fsel( 3, BCM2835_GPIO_FSEL_OUTP); //RPI_BPLUS_GPIO_J8_05= GPIO3
}

Responder
heli
Respuestas: 748
 Heli
(@heli)
Ardero
Registrado: hace 19 años

Has consultado esto?: http://codeandlife.com/2012/07/03/benchmarking-raspberry-pi-gpio-speed/

Responder
Página 1 / 2
Compartir: