Advertisement
otakus

Untitled

Nov 2nd, 2012
104
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 14.52 KB | None | 0 0
  1. #include <Wire.h>
  2.  
  3. enum {x,y,z};
  4. enum {ac1,ac2,ac3,ac4,ac5,ac6,b1,b2,mb,mc,md};
  5. enum {temp,pressure,altitude};
  6. enum {initTemp,getTemp,initPres,getPres};
  7.  
  8. #define ACCEL_ADDRESS (0x53)     //Accel address, 10 bit res, 13bit at 16g. Setup function needs modification if using 13 bit data
  9. #define ACCEL_ID 0xE5            //Devide ID, used to confirm correct device is attached to address
  10. #define ACCEL_SENSITIVITY 0b01   //Set sensitivity +/-: 0b00 2g, 0b01 4g, 0b10 8g, 0b11 16g
  11. byte accel_buff[6];
  12. int  accel_data[3];
  13.  
  14. #define GYRO_ADDRESS (0x69)      //Gyro address, 16 bit res
  15. #define GYRO_ID 0b11010011       //Devide ID, used to confirm correct device is attached to address
  16. #define GYRO_SENSITIVITY 0b11    //Set sensitivity in dps: 0b00 250, 0b01 500, 0b10 2000, 0b11 2000
  17. byte gyro_buff[6];
  18. int  gyro_data[3];
  19. byte  gyro_temp;
  20.  
  21. #define MAG_ADDRESS (0x1E)       //Mag address, 12 bit res
  22. #define MAG_ID1 0b01001000       //Device ID, used to confirm correct device is attached to address. Mag has 3 ID bytes with ACII values: "H4C"
  23. #define MAG_ID2 0b00110100
  24. #define MAG_ID3 0b00110011
  25. #define MAG_GAIN 0x01            //Range(gain control) +/- Ga / LSB per Gauss(0x00-0x07): 0x00 0.88ga/1370, 0x01 1.3ga/1090(default), 0x02 1.9ga/820,0x03 2.5ga/660, 0x04 4.0ga/440, 0x05 4.7ga/390, 0x06 5.6ga/330, 0x07 8.1ga/230
  26. byte mag_buff[6];
  27. int mag_data[3];
  28. int olddata[2];
  29. float heading;
  30.  
  31. #define BAR_ADDRESS (0b1110111)  //Bar address, 16 bit res(preasure data up to 19 bit)
  32. #define BAR_SENSITIVITY 3        //Bar sensitivity(resolution): 0=ultra low power(4.5ms delay), 1=standard(7.5ms delay), 2=High resolution(13.5ms delay), 3=Ultra high resoltuion(25.5ms delay)
  33. #if (BAR_SENSITIVITY==0)         //Set delay time according to sensitivity, does not need to be changed
  34.   #define BAR_PRESDELAY 5
  35. #elif (BAR_SENSITIVITY==1)
  36.   #define BAR_PRESDELAY 8
  37. #elif (BAR_SENSITIVITY==2)
  38.   #define BAR_PRESDELAY 14
  39. #elif (BAR_SENSITIVITY==3)
  40.   #define BAR_PRESDELAY 26
  41. #endif
  42. #define BAR_TEMPDELAY 5          //4.5ms delay required to measure temp
  43. uint16_t bar_registers[]={0xAA,0xAC,0xAE,0xB0,0xB2,0xB4,0xB6,0xB8,0xBA,0xBC,0xBE};
  44. byte bar_buff[3];
  45. int16_t  bar_calib[11];
  46. int32_t bar_data[3];
  47. //Calculation variables:
  48. int32_t b5;
  49. //Bar state machine variables:
  50. byte bar_state=initTemp;
  51. unsigned long bar_timers[2];
  52.  
  53. void setup()
  54. {
  55.   Wire.begin();                  // join i2c bus (address optional for master)
  56.   Serial.begin(115200);          // start serial for output. Make sure you set your Serial Monitor to the same!
  57.   setupAccel();
  58.   setupGyro();
  59.   setupMag();
  60.   setupBar();
  61. }
  62.  
  63. void loop(){
  64.   //Accel:
  65.     readAccel();
  66.     displayAccel();
  67.   //Mag:
  68.     readMagRaw();
  69.     displayMag();
  70.   //Gyro:
  71.     readGyro();
  72.     displayGyro();
  73.   //Bar:
  74.     readBar();
  75.     displayBar();
  76.  
  77.   Serial.println();
  78. }
  79.  
  80. /*-----------------------------------------------------------------Sensor functions---------------------------------------------------*/
  81. //---------------Barometer
  82. void setupBar(){
  83.   for(int i=0;i<sizeof(bar_registers);i++){
  84.     readFrom(BAR_ADDRESS, bar_registers[i], 2, bar_buff);
  85.     bar_calib[i]=(bar_buff[0]<<8)|bar_buff[1];
  86.   }
  87. }
  88. void readBar(){
  89.   int32_t b3,b6,x1,x2,x3;
  90.   uint32_t b4,b7;
  91.  
  92.   switch(bar_state){
  93.     case initTemp:
  94.       bar_state=getTemp;
  95.       writeTo(BAR_ADDRESS, 0xF4, 0x2E);
  96.       bar_timers[temp]=millis();
  97.       break;
  98.     case getTemp:
  99.       if(millis()>bar_timers[temp]+BAR_TEMPDELAY){
  100.         bar_state=initPres;
  101.         readFrom(BAR_ADDRESS, 0xF6, 2, bar_buff);
  102.         bar_data[temp]=(bar_buff[0]<<8)|bar_buff[1];
  103.         x1=((bar_data[temp]-(uint16_t)bar_calib[ac6])*(uint16_t)bar_calib[ac5])>>15;
  104.         x2=((int32_t)bar_calib[mc]<<11)/(x1+bar_calib[md]);
  105.         b5=x1+x2;
  106.         bar_data[temp]=(b5+8)>>4;
  107.       }
  108.       break;
  109.     case initPres:
  110.       bar_state=getPres;
  111.       writeTo(BAR_ADDRESS, 0xF4, 0x34+(BAR_SENSITIVITY<<6));
  112.       bar_timers[pressure]=millis();
  113.       break;
  114.     case getPres:    
  115.       if(millis()>bar_timers[pressure]+BAR_PRESDELAY){
  116.         if(millis()>bar_timers[temp]+1000)
  117.           bar_state=initTemp;
  118.         else
  119.           bar_state=initPres;
  120.         readFrom(BAR_ADDRESS, 0xF6, 3, bar_buff);
  121.         bar_data[pressure]=((((uint32_t)bar_buff[0])<<16)|((uint32_t)bar_buff[1]<<8)|bar_buff[2])>>(8-BAR_SENSITIVITY);
  122.         b6=b5-4000;
  123.         x1=(bar_calib[b2]*(b6*b6)>>12)>>11;
  124.         x2=(bar_calib[ac2]*b6)>>11;
  125.         x3=x1+x2;
  126.         b3=(((((int32_t)bar_calib[ac1])*4+x3)<<BAR_SENSITIVITY)+2)>>2;
  127.         x1=(bar_calib[ac3]*b6)>>13;
  128.         x2=(bar_calib[b1]*((b6*b6)>>12))>>16;
  129.         x3=((x1+x2)+2)>>2;
  130.         b4=((uint16_t)bar_calib[ac4]*(uint32_t)(x3+32768))>>15;
  131.         b7=((uint32_t)(bar_data[pressure]-b3)*(50000>>BAR_SENSITIVITY));
  132.        
  133.         if(b7<0x80000000)
  134.           bar_data[pressure]=(b7<<1)/b4;
  135.         else
  136.           bar_data[pressure]=(b7/b4)<<1;
  137.         x1=(bar_data[pressure]>>8)*(bar_data[pressure]>>8);
  138.         x1=(x1*3038)>>16;
  139.         x2=(-7357*bar_data[pressure])>>16;
  140.         bar_data[pressure]+=((x1+x2+3791)>>4);
  141.       }
  142.       break;
  143.     default:
  144.       Serial.println("Error in bar_state!");
  145.   }
  146. }
  147. void displayBar(){
  148.   String s;
  149.   s+="   Bar Temp:";
  150.   s+=pad(bar_data[temp],5);
  151.   s+=" Preasure:";
  152.   s+=bar_data[pressure];
  153.   s+=" Altitude:";
  154.   s+=pad(bar_data[altitude],5);
  155.   Serial.print(s);
  156. }
  157.  
  158. //---------------Accelerometer
  159. void setupAccel(){
  160.   readFrom(ACCEL_ADDRESS, 0x00, 1, accel_buff);                                                                          //Read ID of accel
  161.   checkID(ACCEL_ID,accel_buff[0]);                                                                                       //Verify match of expected to received
  162.   //                             x-------   -x------   --x-----   ----x---   -----x--     ------xx
  163.   writeTo(ACCEL_ADDRESS, 0x31, 0b00000000|0b00000000|0b00000000|0b00000000|0b00000000|ACCEL_SENSITIVITY);                //DATA_FORMAT register: First bit is self test: 0=disabled, 1=enable(offset output data). Second bit is spi interface: 0=4 wire, 1=3 wire. Third bit inverts INT active state: 0=active high, 1=active low. Fourth bit unused. Fifth bit is full resolution mode: 0=10 bit mode where scale and g-range change with sensitivity(range), 1=output resolution increases with range to maintain 4mg/LSB scale factor. Sixth bit is for justify: 0=right justified with sign extension, 1=left(MSB) justified. Last two bits set sensitivity(range).
  164.   //                             --x-----   ---x----   ----x---   -----x--   ------xx
  165.   writeTo(ACCEL_ADDRESS, 0x2D, 0b00000000|0b00000000|0b00001000|0b00000000|0b00000000);                                  //POWER_CTL register: First two bits are unused. Third bit is link state: Reference datasheet. Fourth bit is AUTO_SLEEP mode: 0=disabled, 1=reference datasheet.Fifth bit is Measure mode: 0=standby, 1=measurement mode. Sixth bit is sleep mode: 0=normal mode,1=sleep mode. Last two bits are for WAKUP: sample rate to set when waking up.
  166. }
  167. void readAccel() {
  168.   readFrom(ACCEL_ADDRESS, 0x32, 6, accel_buff);                                   //read the acceleration data from the ADXL345
  169.   accel_data[x]=(((int)(accel_buff[1]<<6))<<2)|accel_buff[0];                     //10 bit numbers, LSB first in array. Could <<8 but this prevents rollover and bad data on unused bits.
  170.   accel_data[y]=(((int)(accel_buff[3]<<6))<<2)|accel_buff[2];
  171.   accel_data[z]=(((int)(accel_buff[5]<<6))<<2)|accel_buff[4];
  172. }
  173. void displayAccel(){
  174.   String s;
  175.   s+="   Accel X:";
  176.   s+=pad(accel_data[x]);
  177.   s+=" Y:";
  178.   s+=pad(accel_data[y]);
  179.   s+=" Z:";
  180.   s+=pad(accel_data[z]);
  181.   Serial.print(s);
  182. }
  183. //---------------Gyro
  184. void setupGyro(){
  185.   readFrom(GYRO_ADDRESS, 0x0F, 1, gyro_buff);                                                            //Read ID of Gyro
  186.   checkID(GYRO_ID,gyro_buff[0]);                                                                         //Verify match of expected to received
  187.   //                            xx------   --xx----   ----x---   -----xxx  
  188.   writeTo(GYRO_ADDRESS, 0x20, 0b00000000|0b00110000|0b00001000|0b00000111);                              //CTRL_REG1: First two bits are data rate in Hz: 00=100,01=200,10=400,11=800. Second two bits are bandwidth(look in datasheet for details). Fith bit is Power Down Enable: 0=power down mode, 1=Normal/sleep mode.Last 3 bits are ZYX Axis enable bits: 0=disabled,1=Enabled.
  189.   readFrom(GYRO_ADDRESS, 0x21, 1, gyro_buff);                                                            //CTRL_REG2 writes first two bits on boot that shouldn't be changed, so let's first read them so when we write new data we don't change those bits. Recyling the gyro_buffer since there is no need to waste memory on more variables.
  190.   //                              xx------   --xx----   ----xxxx
  191.   writeTo(GYRO_ADDRESS, 0x21, gyro_buff[0]|0b00000000|0b00000000);                                       //CTRL_REG2: First two bits should remain unchanged so write them as we read them. Second two bits are high pass filter mode selection: 00=Normal mode(reset reading HP_RESET_FILTER),01=reference signal for filtering, 10=normal mode, 11=autoreset on interrupt event. Last 4 bits are high pass filter cut off frequency selection(refer to datasheet for table).
  192.   //                            x-------   -x------         --xx----      -----xx-   -------x  
  193.   writeTo(GYRO_ADDRESS, 0x23, 0b00000000|0b00000000|GYRO_SENSITIVITY<<4|0b00000000|0b00000000);          //CTRL_REG4: First bit is block data update: 0=continuous, 1=output registers not updated until MSG and LCB reading. Second bit bit/little endian data selection: 0=data LSB at lower address,1=data MSB at lower address. Next two bits are full scale selection(sensitivity in dps. Fith bit is unused. Sixth and Seventh bit are self test enable: 00=disabled, others=see datasheet table. Last bit is SPI interface mode(not used since we're using i2c): 0=4 wire, 1=3 wire.
  194.   //                            x-------   -x------   ---x----   ----xx--   ------xx  
  195.   writeTo(GYRO_ADDRESS, 0x24, 0b00000000|0b00000000|0b00000000|0b00000000|0b00000000);                   //CTRL_REG5:  First bit is reboot memeory content: 0=normal mode, 1=reboot memory content. Second bit is FIFO enable. Third bit unused. Fourth bit is high pass filter enable: 0=disabled, 1=enabled. Bits five and six used for INT1 selection configuration(see datasheet for details). Last two bits are for Out selection configuration(see datasheet for details).
  196. }
  197. void readGyro() {
  198.   readFrom(GYRO_ADDRESS, 0x26, 1, gyro_buff);                                    //Read temp for compensation or other uses
  199.   gyro_temp=gyro_buff[0];
  200.   readFrom(GYRO_ADDRESS, 0b10000000|0x28, 6, gyro_buff);                         //Read the rate data from the L3G4200D, 0b10000000 is require for multi byte readout
  201.   gyro_data[x]=((((int)(gyro_buff[1]))<<8)|gyro_buff[0])-1;                      //Full 16 bit numbers, LSB first, goes out of range for signed int so need to subtract 1 to keep it within –32768 to 32767
  202.   gyro_data[y]=((((int)(gyro_buff[3]))<<8)|gyro_buff[2])-1;
  203.   gyro_data[z]=((((int)(gyro_buff[5]))<<8)|gyro_buff[4])-1;
  204. }
  205. void displayGyro(){
  206.   String s;
  207.   s+="   Gyro X:";
  208.   s+=pad(gyro_data[x],5);
  209.   s+=" Y:";
  210.   s+=pad(gyro_data[y],5);
  211.   s+=" Z:";
  212.   s+=pad(gyro_data[z],5);
  213.   s+=" Temp:";
  214.   s+=pad(gyro_temp);
  215.   Serial.print(s);
  216. }
  217.  
  218.  
  219. //---------------Magnetometer
  220. void setupMag(){
  221.   readFrom(MAG_ADDRESS, 0x0A, 3, mag_buff);                                  //Read the 3 ID bytes of Mag
  222.   checkID(MAG_ID1,mag_buff[0]);                                              //Verify first ID byte.
  223.   checkID(MAG_ID2,mag_buff[1]);                                              //Verify second ID byte.
  224.   checkID(MAG_ID3,mag_buff[2]);                                              //Verify third ID byte.
  225.   //                           x-------   -xx-----   ---xxx--   ------xx
  226.   writeTo(MAG_ADDRESS, 0x00, 0b10000000|0b01100000|0b00011000|0b00000000);   //First bit needed to clear, next 2 bits sample average: 00=1 01=2 10=4 11=8, next 3 bits data output rate 0b000-0b110(0.75,1.5,3,7.5,15,30,75 Hz) 160 Hz can be achieve in single shot sample mode, last 2 bits measurement config bits 0b00-0b11(normal, posative bias, negative bias, reserved-do not use)  
  227.   writeTo(MAG_ADDRESS, 0x01, MAG_GAIN<<5);                                   //Set first 3 bits for gain, last 5 need to be 0 to clear
  228.   writeTo(MAG_ADDRESS, 0x02, 0x00);                                          //Set sampling mode: 0x00 Continuous, 0x01 single shot, 0x03 idle
  229. }
  230. void readMagRaw(){
  231.   readFrom(MAG_ADDRESS, 0x03, 6, mag_buff);                                  //read data from the HMC5883L
  232.   mag_data[x]=(((int)(mag_buff[0]<<4))<<4)|mag_buff[1];                      //12 bit numbers. Could <<8 but this prevents bad data on unused bits.
  233.   mag_data[z]=(((int)(mag_buff[2]<<4))<<4)|mag_buff[3];
  234.   mag_data[y]=(((int)(mag_buff[4]<<4))<<4)|mag_buff[5];
  235. }
  236.  
  237. void displayMag(){
  238.   String s;
  239.   s+="   Mag X:";
  240.   s+=pad(mag_data[x]);
  241.   s+=" Y:";
  242.   s+=pad(mag_data[y]);
  243.   s+=" Z:";
  244.   s+=pad(mag_data[z]);
  245.   s+=" H:";
  246.   s+=pad(heading);
  247.   Serial.print(s);
  248. }
  249.  
  250. /*------------------------------------------------------------------i2c functions------------------------------------------------------*/
  251. void writeTo(byte device, byte address, byte val) {
  252.   Wire.beginTransmission(device);
  253.   Wire.write(address);
  254.   Wire.write(val);
  255.   Wire.endTransmission();
  256. }
  257.  
  258. void readFrom(byte device, byte address, byte num, byte buff[]) {
  259.   Wire.beginTransmission(device);
  260.   Wire.write(address);
  261.   Wire.endTransmission();
  262.  
  263.   Wire.beginTransmission(device);
  264.   Wire.requestFrom(device, num);
  265.  
  266.   for(int i=0;i<num;i++){
  267.     if(Wire.available())
  268.       buff[i]=Wire.read();
  269.     else
  270.       buff[i]=0;
  271.   }
  272.   Wire.endTransmission();
  273. }
  274.  
  275. /*------------------------------------------------------Utility functions-----------------------------------------------------------*/
  276. void checkID(uint16_t expected, uint16_t received){
  277.   if(received!=expected){
  278.     Serial.print("Wrong device ID. ");
  279.     Serial.print("Expected: 0x");
  280.     Serial.print(expected,HEX);
  281.     Serial.print("(0b");
  282.     Serial.print(expected,BIN);
  283.     Serial.print(") but received: 0x");
  284.     Serial.print(received,HEX);
  285.     Serial.print("(0b");
  286.     Serial.print(received,BIN);
  287.     Serial.println(")");
  288.     while(true);
  289.   }
  290. }
  291. String pad(int number){
  292.   return pad(number,4);
  293. }
  294. String pad(int number,int digits){
  295.   String ret="";
  296.   if(number<0){
  297.     number*=-1;
  298.     ret+="-";
  299.   }
  300.   else{
  301.     ret+=" ";
  302.   }
  303.   for(int i=0; i < (digits-1) - byte(log10(number)); i++)
  304.     ret+='0';
  305.   ret+=number;
  306.   return ret;
  307. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement