public
Created

Vibration sensor using accelerometer on Hannah

  • Download Gist
hannah-motiondetect.nut
Squirrel
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
// Vibration sensor using accelerometer on Hannah
 
//I2C Addresses
const i2c_ioexp = 0x7C;
const i2c_temp = 0x98;
const i2c_als = 0xE8;
const i2c_accel = 0x38;
 
//----------------------------------------
//-- Configure I2C
//----------------------------------------
hardware.configure(I2C_89);
local i2c = hardware.i2c89;
 
//----------------------------------------
//-- IO Expander Functions
//----------------------------------------
local function ioexp_read(addr) {
local result = i2c.read(i2c_ioexp, format("%c", addr), 1);
if (result == null) {
server.log("i2c read fail");
return -1;
} else return result[0];
}
 
local function ioexp_write(addr, data) {
i2c.write(i2c_ioexp, format("%c%c",addr, data));
}
 
local function ioexp_writebit(addr, bitn, level) {
// read modify write
local reg = ioexp_read(addr);
reg = (level==0)?(reg&~(1<<bitn)) : (reg | (1<<bitn));
ioexp_write(addr, reg)
}
 
local function ioexp_modify_write(addr, data, mask) {
local reg = ioexp_read(addr);
reg = (reg & ~mask) | (data & mask);
ioexp_write(addr, reg);
}
 
local function ioexp_setpin(gpio, level) {
ioexp_writebit(gpio>=8?0x10:0x11, gpio&7, level?1:0);
}
 
local function ioexp_setdir(gpio, output) {
ioexp_writebit(gpio>=8?0x0e:0x0f, gpio&7, output?0:1);
}
 
local function ioexp_setpullup(gpio, enable) {
ioexp_writebit(gpio>=8?0x06:0x07, gpio&7, enable);
}
 
local function ioexp_setirqmask(gpio, enable) {
ioexp_writebit(gpio>=8?0x12:0x13, gpio&7, enable);
}
 
local function ioexp_setirqedge(gpio, rising, falling) {
local addr = 0x17 - (gpio>>2);
local mask = 0x03 << ((gpio&3)<<1);
local data = (2*falling + rising) << ((gpio&3)<<1);
ioexp_modify_write(addr, data, mask);
}
 
local function ioexp_clearirq(gpio) {
ioexp_writebit(gpio>=8?0x18:0x19, gpio&7, 1);
}
 
local function ioexp_readpin(gpio) {
return (ioexp_read(gpio>=8?0x10:0x11)&(1<<(gpio&7)))?1:0;
}
 
local function ioexp_setled(gpio, led) {
ioexp_writebit(gpio>=8?0x20:0x21, gpio&7, led);
}
 
local function ioexp_update_leds(r,g,b) {
ioexp_write(0x3b, g);
ioexp_write(0x40, b);
ioexp_write(0x45, r);
}
 
//LED Driver Enable
ioexp_modify_write(0x01, 0xE0, 0xFF);
ioexp_modify_write(0x0f, 0xE0, 0x00);
ioexp_modify_write(0x0b, 0xE0, 0xFF);
ioexp_modify_write(0x21, 0xE0, 0xFF);
ioexp_write(0x1e, 0x50);
ioexp_write(0x1f, 0x10);
ioexp_update_leds(0,0,0);
ioexp_setpin(5, 0);
ioexp_setpin(6, 0);
ioexp_setpin(7, 0);
 
// Enable Potentiometer
ioexp_setpin(8, 0);
ioexp_setdir(8, 1);
hardware.pin2.configure(ANALOG_IN);
 
// Enable accelerometer
local e = i2c.write(i2c_accel, "\x20\x47");
 
local out = OutputPort("Acceleration", "number")
 
local averageX = 0
local averageY = 0
local averageZ = 0
 
local warmup = 0
 
local exponentialFactor = 0.9
 
function poll() {
imp.wakeup(0.05, poll)
local accel = i2c.read(i2c_accel, "\x29", 1) + i2c.read(i2c_accel, "\x2B", 1) + i2c.read(i2c_accel, "\x2D", 1)
local x = ((accel[0] + 128) % 256) - 128.0
local y = ((accel[1] + 128) % 256) - 128.0
local z = ((accel[2] + 128) % 256) - 128.0
averageX = averageX * exponentialFactor + x * (1-exponentialFactor)
averageY = averageY * exponentialFactor + y * (1-exponentialFactor)
averageZ = averageZ * exponentialFactor + z * (1-exponentialFactor)
local motion = math.abs(x-averageX) + math.abs(y-averageY) + math.abs(z-averageZ)
if(motion > 5 && warmup > 3/(1-exponentialFactor)) {
server.log(format("triggered! %d", motion))
} else {
warmup += 1
}
}
 
poll()
 
imp.configure("Vibration sensor", [], [out])

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.