Magazine Opinioni

Primi esperimenti con la BeagleBone Black – Collegare 10DOF via I2C

Creato il 03 maggio 2014 da Michelepinassi @michele_pinassi
Verifica questa notizia !10DOF e uBlox GPS modules

10DOF e U-blox NEO-6M GPS modules

Dopo circa 30 giorni ho finalmente ricevuto il pacco dalla Cina, acquisto di pochi dollari su eBay, con i due moduli ordinati:

  • 10DOF Module 9-axis Attitude Indicator L3G4200D ADXL345 HMC5883L BMP085 Module
  • GPS U-blox NEO-6M Module

Questa sera ho deciso di giocare un po’ con il 10DOF, un piccolo moduletto molto compatto con a bordo:

  • L3G4200D - Giroscopio 3 assi (L3G4200D Datasheet)
  • ADXL345 - Accelerometro tre assi (ADXL345 Datasheet)
  • HMC5883L – Compasso digitale 3 assi (HMC5883L Datasheet)
  • BMP085 – Sensore barometrico e termometro (BMP085 Datasheet)
10DOF I2C pinouts

10DOF I2C pinouts

Il tutto accessibile mediante il medesimo bus I2C, ai seguenti indirizzi:

I2C Address 0x1E è il HMC5883L
I2C Address 0×53 è il ADXL345
I2C Address 0×69 è il L3G4200D
I2C Address 0×77 è il BMP085

La fonte originale, in inglese, a questo sito web: http://www.forkrobotics.com/2013/06/using-the-gy80-10dof-module-with-arduino/

BMP085

Per iniziare ho deciso di provare a collegare il modulo al mio BeagleBone Black, via bus I2C, e provare ad interrogare il sensore barometrico/termometro BMP085.

Connessioni

Connessioni

Per prima cosa, i cablaggi. Cercando lo schema “pinouts” della BeagleBoard Black, scopro che ci sono ben due bus I2C disponibili, sul bus P9 (posto a sinistra, con il connettore RJ45 in alto):

  • I2C BUS 1 ai pin 17 (SCL) e 18 (SDA)
  • I2C BUS 2 ai pin 19 (SCL) e 20 (SDA)
Informazioni più dettagliate sul bus I2C nella Beagle Board Bone al sito http://datko.net/2013/11/03/bbb_i2c/ 

Considerando che il modulo può essere alimentato direttamente dai 3.3V forniti dalla BeagleBoard, ho preso la mia bella breadboard ed ho collegato i 4 fili richiesti per iniziare a giocare:

  • PIN 2 = GND
  • PIN 4 = Vcc 3V
  • PIN 17 = SCL
  • PIN 18 = SDA

Gli altri piedini del 10 DOF non sono utilizzati. Accendiamo ovviamente la BBB e, da root, abilitiamo  il bus I2C con il seguente comando:

echo BB-I2C1 > /sys/devices/bone_capemgr.9/slots

A questo punto possiamo iniziare ad esplorare il fantastico bus i2c con il comando ‘i2cdetect‘:

root@arm:~/C# i2cdetect -l
i2c-0 i2c OMAP I2C adapter I2C adapter
i2c-1 i2c OMAP I2C adapter I2C adapter
i2c-2 i2c OMAP I2C adapter I2C adapter
root@arm:~/C# 

In questo caso ci interessa il bus 2 (i2c-2):

root@arm:~/C# i2cdetect -r 2
WARNING! This program can confuse your I2C bus, cause data loss and worse!
I will probe file /dev/i2c-2 using read byte commands.
I will probe address range 0x03-0x77.
Continue? [Y/n] 
 0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- 1e -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- 53 -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- 69 -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- 77 
root@arm:~/C#

Come vedete, il sistema identifica con successo i dispotivi agli indirizzi 0x1e, 0×53,0×69 e 0×77 (descritti prima, all’inizio dell’articolo).

A questa pagina trovate molta documentazione in merito alle implementazioni su Linux delll’interfaccia I2C: https://www.kernel.org/doc/Documentation/i2c/dev-interface

A questo punto si tratta di scrivere qualche riga di codice per vedere se il tutto funziona. Cercando in rete, ho trovato qualche pagina con gli algoritmi per interrogare il BMP085 in uno pseudo-C per Arduino, dai quali ho preso spunto per scrivere questo veloce programmino compilato direttamente sulla BBB, che potete usare come base per i vostri esperimenti:

/* I2C test */

#include 
#include 
#include 
#include 

#define DEBUG

// Calibration values
int ac1;
int ac2;
int ac3;
unsigned int ac4;
unsigned int ac5;
unsigned int ac6;
int b1;
int b2;
int mb;
int mc;
int md;

unsigned char I2C_readByte(int file, __u8 regs) {
 unsigned char res;

 usleep(5000); // Wait some time...
 res = i2c_smbus_read_byte_data(file, regs);
 if (res < 0) {
 printf("Error reading data from 0x%x register on i2c bus\n", regs);
 return -1;
 } 
#ifdef DEBUG
 printf("[DEBUG] 0x%x => 0x%x\n",regs,res);
#endif
 return res;
}

int I2C_readWord(int file, __u8 regs) {
 unsigned char msb,lsb;
 int res;

 msb = I2C_readByte(file,regs);
 lsb = I2C_readByte(file,regs+1);

 res = (int)msb << 8 | lsb;

#ifdef DEBUG
 printf("[DEBUG] %d\n",res);
#endif

 return res; 
}


int I2C_writeWord(int file, __u8 regs, __u16 value) {
 int res;
 res = i2c_smbus_write_word_data(file, regs, value);
 if(res < 0) {
 printf("Error writing 0x%x to 0x%x register on i2c bus\n",value, regs);
 return -1;
 }
 return 1;
}

float BMP085_readTemp(file) {
 long x1, x2, b5;
 int res;
 float temp;

 I2C_writeWord(file,0xF4,0x2E);
 usleep(45000); // Wait at least 4,5 ms
 res = I2C_readWord(file,0xF6);

 x1 = ((long)res - (long)ac6)*(long)ac5 >> 15;
 x2 = ((long)mc << 11)/(x1 + md);
 b5 = x1 + x2;

 temp = ((b5 + 8) >> 4); // Temp in 0.1°C
// temp = temp / 10;

 return temp;
}

void BMP085_getCalibration(file) {
/*
 ac1 = 408;
 ac2 = -72;
 ac3 = -14383;
 ac4 = 32741;
 ac5 = 32757;
 ac6 = 23153;
 b1 = 6190;
 b2 = 4;
 mb = -32767;
 mc = -8711;
 md = 2868; 
*/

 ac1 = I2C_readWord(file,0xAA);
 ac2 = I2C_readWord(file,0xAC);
 ac3 = I2C_readWord(file,0xAE);
 ac4 = I2C_readWord(file,0xB0);
 ac5 = I2C_readWord(file,0xB2);
 ac6 = I2C_readWord(file,0xB4);
 b1 = I2C_readWord(file,0xB6);
 b2 = I2C_readWord(file,0xB8);
 mb = I2C_readWord(file,0xBA);
 mc = I2C_readWord(file,0xBC);
 md = I2C_readWord(file,0xBE);
}

void main() {
 int file;
 int adapter_nr = 2;
 int addr = 0x77;
 char filename[20];
 float temp;

 printf("Open BMP085 I2C device @ 0x77...");

 snprintf(filename, 19, "/dev/i2c-%d", adapter_nr);
 file = open(filename, O_RDWR);
 if (file < 0) {
 printf("Error while opening device %s: %d error\n",filename,errno);
 exit(1);
 }
 
 if (ioctl(file, I2C_SLAVE, addr) < 0) {
 printf("Error while set I2C address: %d error\n",errno);
 exit(1);
 }

 printf("OK !\nGet calibration data...");

 BMP085_getCalibration(file);

 printf("OK !\n");

 while(1) {
 temp = BMP085_readTemp(file);
 printf("Temperature: %4.2f °C\n",temp);
 sleep(1);
 }
}

compilatelo con un semplice “gcc i2c.c -o i2c”.

Prima di poter compilare il programma dovete installare sulla BBB le build-essential e la libreria di sviluppo libi2c-dev

Vai, le sperimentazioni sono iniziate: buon divertimento !


Potrebbero interessarti anche :

Ritornare alla prima pagina di Logo Paperblog

Possono interessarti anche questi articoli :