This page is about Arduino stuff.
Source code for Magnetic Compass Sensor HDMM01
Header
#ifndef COMPASS_HDMM01_h #define COMPASS_HDMM01_h #include <Arduino.h> #include "TypesLib.h" class CompassHDMM01 { public: static const int HDMM01_1 = 0x30; static const int HDMM01_2 = 0x32; static const int HDMM01_3 = 0x34; static const int HDMM01_4 = 0x36; static const byte TAKE_MEASURE = 0x01; static const byte SET_COIL = 0x02; static const byte RESET_COIL = 0x04; int i2addr; Vec2i offs; double declination; CompassHDMM01(int i2addr); void resetSetCoil(); Vec2i getReading(bool resetCoil); void calibrateMinMax(long num, long t, bool resetCoil); void calibrateAvg(long num, long t, bool resetCoil); void calibrateLS(long num, long t, bool resetCoil); // calculate the angle of the magnetic field in grad // 0 Deg = North // 90 Deg = East // +-180 Deg = South // -90 Deg = West template <typename T> double calcAngleDeg(Vec2<T> const &reading) { double angle = atan2(reading.y, reading.x) * 180.0 / 3.1415927410 + declination; return angle; } // calculate the angle of the magnetic field in rads // 0 Rad = North // PI/2 Rad = East // +-PI Rad = South // -PI/2 Rad = West template <typename T> double calcAngleRad(Vec2<T> const &reading) { double angle = atan2(reading.y, reading.x) + declination * PI / 180.0; return angle; } // caclulate the strenght of the magnetic field in gauss static double calcStrength(Vec2i const &reading) { double x = (double)reading.x / 512.0; double y = (double)reading.y / 512.0; double strength = sqrt(x*x + y*y); return strength; } // converts the reading to gauss static Vec2d convertGauss(Vec2i const &reading) { Vec2d gauss; gauss.x = (double)reading.x / 512.0; gauss.y = (double)reading.y / 512.0; return gauss; } }; #endif
Source
#include <Wire.h> #include "CompassHDMM01.h" // Constructor CompassHDMM01::CompassHDMM01(int i2addr) { this->i2addr = i2addr; // set offset do default value // 2048 is the value for zero field. offs.x = 2048; offs.y = 2048; declination = 0.0; } // Reset and Set coils void CompassHDMM01::resetSetCoil() { // reset coil Wire.beginTransmission(i2addr); Wire.write(0x00); Wire.write(RESET_COIL); Wire.endTransmission(); delay(1); // set coil Wire.beginTransmission(i2addr); Wire.write(0x00); Wire.write(SET_COIL); Wire.endTransmission(); delay(1); } // Readout compass values Vec2i CompassHDMM01::getReading(bool resetCoil) { Vec2i reading; byte MsbX,LsbX,MsbY,LsbY; int x,y; if (resetCoil) { resetSetCoil(); } // take measurement Wire.beginTransmission(i2addr); Wire.write(0x00); // write to address 0x00 Wire.write(TAKE_MEASURE); Wire.endTransmission(); delay(5); // read data Wire.beginTransmission(i2addr); Wire.write(0x01); // read from address 0x01 Wire.requestFrom(i2addr, 4); while(Wire.available() < 4); MsbX = Wire.read(); LsbX = Wire.read(); MsbY = Wire.read(); LsbY = Wire.read(); Wire.endTransmission(); reading.x=(((MsbX & 0x0f) << 8) | LsbX) - offs.x; reading.y=(((MsbY & 0x0f) << 8) | LsbY) - offs.y; return reading; } // Calibrate between min and max values. void CompassHDMM01::calibrateMinMax(long num, long t, bool resetCoil) { Vec2<int> min, max; Vec2i reading; min = max = getReading(resetCoil); for (int i=0; i < num; i++) { reading = getReading(resetCoil); if (reading.x < min.x) { min.x = reading.x; } else if (reading.x > max.x) { max.x = reading.x; } if (reading.y < min.y) { min.y = reading.y; } else if (reading.y > max.y) { max.y = reading.y; } delay(t); } offs.x += (min.x + max.x) / 2; offs.y += (min.y + max.y) / 2; } // Calibreate compass by averaging all points. // Not good. Works only with constant rotation speed. void CompassHDMM01::calibrateAvg(long num, long t, bool resetCoil) { Vec2<long> sum; Vec2i reading; sum.x = 0; sum.y = 0; for (int i=0; i < num; i++) { reading = getReading(resetCoil); sum.x += reading.x; sum.y += reading.y; delay(t); } offs.x += (sum.x) / num; offs.y += (sum.y) / num; } // Calibrating compass with Least Sqare Method for circles. // Yes, it is black magic. void CompassHDMM01::calibrateLS(long num, long t, bool resetCoil) { Vec2i reading; /* Matrix B a b c b e f c f i */ long long Ba = 0; long long Bb = 0; long long Bc = 0; long long Be = 0; long long Bf = 0; long long Bi = 0; long long y; // Vector C [x y z] long long Cx = 0; long long Cy = 0; long long Cz = 0; // Vector Z [x y z] long long Zx; long long Zy; long long Zz; // start meassurement for (int i=0; i < num; i++) { reading = getReading(resetCoil); /* DEBUG Serial.print("new Vector<double>("); Serial.print(reading.x); Serial.print(","); Serial.print(reading.y); Serial.println("),"); */ Ba += reading.x * reading.x; Bb += reading.x * reading.y; Bc += reading.x; Be += reading.y * reading.y; Bf += reading.y; y = reading.x * reading.x + reading.y * reading.y; Cx += reading.x * y; Cy += reading.y * y; Cz += y; delay(t); } Bi = num; // Solve B * z = c // Calculate det(B) long long det = Ba * (Be * Bi - Bf * Bf) -Bb * (Bb * Bi - Bf * Bc) +Bc * (Bb * Bf - Be * Bc); /* DEBUG Serial.print("det:"); Serial.println((long)(det/1000000)); */ // Calculate z = B^-1 * c Zx = (( Be * Bi - Bf * Bf) * Cx +(Bc * Bf - Bb * Bi) * Cy +(Bb * Bf - Bc * Be) * Cz) / det; Zy = (( Bf * Bc - Bb * Bi) * Cx +(Ba * Bi - Bc * Bc) * Cy +(Bc * Bb - Ba * Bf) * Cz) / det; Zz = (( Bb * Bf - Be * Bc) * Cx +(Bb * Bc - Ba * Bf) * Cy +(Ba * Be - Bb * Bb) * Cz) / det; offs.x += Zx / 2; offs.y += Zy / 2; //double r = sqrt(Zz + (Zx * Zx + Zy * Zy) / 4); /* DEBUG Serial.print("r:"); Serial.println(r, 3); */ }
Source code for Hummidity Sensor HH10D
Header
#ifndef HUMIDITY_HH10D_H #define HUMIDITY_HH10D_H #include <Arduino.h> #include "TypesLib.h" #include <Wire.h> class HumidityHH10D { public: static const int HH10D = 0x51; int i2addr; int freqIRQ; int sens; int offs; double freq; bool freqReady; HumidityHH10D(int i2addr, int freqIRQ); void getCoeff(); double calcRH(double freq); void startFreq(long timeSpan); protected: static unsigned long cnt; static unsigned long startTime; static unsigned long timeSpan; static HumidityHH10D* cur; static void interrupt() { cnt++; if (millis() >= (startTime + timeSpan)) { unsigned long time = millis(); detachInterrupt(cur->freqIRQ); /* Serial.print("cnt:"); Serial.print(cnt); Serial.print(" time:"); Serial.println(time-startTime); */ cur->freq = (double)cnt * 500.0 / (double)(time - startTime); cur->freqReady = true; cur = NULL; } } }; #endif
Source
#include "HumidityHH10D.h" #include <Wire.h> HumidityHH10D::HumidityHH10D(int i2addr, int freqIRQ) { this->i2addr = i2addr; this->freqIRQ = freqIRQ; } void HumidityHH10D::getCoeff() { byte offs_lsb = 0, offs_msb = 0, sens_lsb = 0, sens_msb = 0; Wire.beginTransmission(i2addr); Wire.write(0x0A); Wire.endTransmission(); Wire.requestFrom(i2addr, 2); if (Wire.available()) sens_msb = Wire.read(); if (Wire.available()) sens_lsb = Wire.read(); Wire.beginTransmission(i2addr); Wire.write(0x0C); Wire.endTransmission(); Wire.requestFrom(i2addr, 2); if (Wire.available()) offs_msb = Wire.read(); if (Wire.available()) offs_lsb = Wire.read(); sens = (sens_msb << 8) | sens_lsb; offs = (offs_msb << 8) | offs_lsb; } double HumidityHH10D::calcRH(double freq) { double rh = ((double)offs - (double)freq) * (double)sens / 4096.0; return rh; } unsigned long HumidityHH10D::cnt = 0; unsigned long HumidityHH10D::startTime = 0; unsigned long HumidityHH10D::timeSpan = 0; HumidityHH10D* HumidityHH10D::cur = NULL; void HumidityHH10D::startFreq(long timeSpan) { if (HumidityHH10D::cur == NULL) { freqReady = false; HumidityHH10D::cnt = 0; HumidityHH10D::startTime = millis(); HumidityHH10D::timeSpan = timeSpan; HumidityHH10D::cur = this; attachInterrupt(freqIRQ, interrupt, CHANGE); } }