Linuxino meet Arduino, discussione

nid69ita:
Supponendo di voler continuare ad utilizzare il C++, su un linuxino, avendo un Linux sotto il sedere, come si "dialoga" con il GPIO e con gli A/D ?

Il C in realtà non prevede nessuna periferica di I/O, questo compito è delegato ad alcune funzioni standard di libreria che devono essere realizzate su misura per ogni hardware, nel caso di Aria con python c'è una apposita libreria che rende facilissimo l'accesso a tutte le periferiche, siamo allo stesso livello di Arduino, con il C il modo più semplice è dichiarare la periferica come un file usando la mappatura predefinita nel kernel, ovviamente le operazioni di lettura e scrittura del file abbinato alla periferica non toccano in nessun modo la flash (SD) salvo la creazione di un file con il nome abbinato alla periferica che ne contiene l'init.
Poi c'è il modo migliore in assoluto per gestire le periferiche che è lo stesso che si usa con tutti i micro quando si vuole ottenere il massimo delle prestazioni, ovvero accedere direttamente ai registri hardware delle stesse, però non è una cosa immediata dallo user space di linux dove gira il tuo programma.

Esempio pratico con il blink, led collegato al GPIO 9, su Aria:

codice python

import ablib
import time
 
print "Blinking led"
print "Type ctrl-C to exit"
 
led = ablib.Pin('W','9','low')
 
while True:
	time.sleep(0.2)
	led.on()
	time.sleep(0.2)
	led.off()

Stessa cosa in C, sembra più complicato in realtà è ugualmente semplice, in più c'è solo la parte di init che con python è gestita dalla libreria e non è direttamente visibile.

#include "stdio.h"
#include "stdlib.h"
#include "unistd.h"

int gpioexport(int gpioid) 
{
	FILE *filestream;

	if ((filestream=fopen("/sys/class/gpio/export","w"))==NULL) {
		printf("Error on export GPIO\n");
		return -1;
	}	
	fprintf(filestream,"%d",gpioid);
	fclose(filestream);
	return 0;
}

int gpiosetdir(int gpioid,char *mode) 
{
	FILE *filestream;
	char filename[50];

	sprintf(filename,"/sys/class/gpio/gpio%d/direction",gpioid);
	if ((filestream=fopen(filename,"w"))==NULL) {
		printf("Error on direction setup\n");
		return -1;
	}	
	fprintf(filestream,mode);
	fclose(filestream);
	return 0;
}

int gpiogetbits(int gpioid) 
{
	FILE *filestream;
	char filename[50];
	char retchar;

	sprintf(filename,"/sys/class/gpio/gpio%d/value",gpioid);
	if ((filestream=fopen(filename,"r"))==NULL) {
		printf("Error on gpiogetbits %d\n",gpioid);
		return -1;
	}	
	retchar=fgetc(filestream);
	fclose(filestream);
	if (retchar=='0') return 0;
	else return 1;
}

int gpiosetbits(int gpioid) 
{
	FILE *filestream;
	char filename[50];

	sprintf(filename,"/sys/class/gpio/gpio%d/value",gpioid);
	if ((filestream=fopen(filename,"w"))==NULL) {
		printf("Error on setbits %d\n",gpioid);
		return -1;
	}	
	fprintf(filestream,"1");
	fclose(filestream);
	return 0;
}

int gpioclearbits(int gpioid) 
{
	FILE *filestream;
	char filename[50];

	sprintf(filename,"/sys/class/gpio/gpio%d/value",gpioid);
	if ((filestream=fopen(filename,"w"))==NULL) {
		printf("Error on clearbits %d\n",gpioid);
		return -1;
	}	
	fprintf(filestream,"0");
	fclose(filestream);
	return 0;
}

int main(void) 
{
	int led = 82;
	
	gpioexport(led);
	gpiosetdir(led,"out");
	for (;;) {
		gpiosetbits(led);
		sleep(1);
		gpioclearbits(led);
		sleep(1);
	}
}