Skip to content

Commit 396e306

Browse files
committed
Initial commit
0 parents  commit 396e306

File tree

8 files changed

+369
-0
lines changed

8 files changed

+369
-0
lines changed

.prettierrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{}

README.md

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# Raspberry Pi / Node.js module for the CAP1188 capacitive touch breakout
2+
3+
The CAP1188 is an 8-channel capacitive touch sensor and is available in a handy [breakout board](https://www.adafruit.com/products/1602). This module enables I2C communication with the chip to easily get information about which pins are being touched. It's based on [Espruino CAP1188 lirrary](http://www.espruino.com/modules/CAP1188.js) which itself is based on the [Adafruit CAP1188 Arduino libary](https://github.com/adafruit/Adafruit_CAP1188_Library).
4+
5+
## Wiring
6+
7+
You can wire this up as follows:
8+
9+
| Device Pin | Pi |
10+
| ---------- | ------------------------------------------------- |
11+
| 1 (GND) | [Ground](https://pinout.xyz/pinout/ground) |
12+
| 2 (VIN) | [3.3v](https://pinout.xyz/pinout/pin1_3v3_power) |
13+
| 3 (SDA) | [BCM 2/SDA](https://pinout.xyz/pinout/pin3_gpio2) |
14+
| 4 (SCK) | [BCM 3/SCL](https://pinout.xyz/pinout/pin5_gpio3) |
15+
16+
## Install
17+
18+
### Enable I2C on the Pi
19+
20+
1. `sudo raspi-config`
21+
2. "Interfacing Options"
22+
3. "I2C"
23+
4. "Would you like the ARM I2C interface to be enabled?" -> "YES"
24+
5. "OK"
25+
6. "Finish"
26+
27+
### Install this library
28+
29+
`npm install --save https://github.com/andrewn/raspi-cap/archive/master.tar.gz`
30+
31+
## Usage
32+
33+
Basic usage:
34+
35+
```js
36+
const connect = require("raspi-cap").connect;
37+
38+
// Connect to the CAP1188 breakout.
39+
// When it's ready, the Promise resolves
40+
// with the CAP1188 instance
41+
connect().then(cap1188 => {
42+
// Returns an array of 8 items for pins C1 - C8
43+
// true indicates a touch, false is no touch
44+
// e.g. C6 is being touched
45+
// [ false, false, false, false, false, true, false, false ]
46+
const touches = cap1188.readTouches();
47+
console.log(touches);
48+
});
49+
```
50+
51+
See the [`examples`](./examples) directory for more examples.
52+
53+
## GUI
54+
55+
There's a tiny GUI you can run:
56+
57+
sudo raspi-cap-debug
58+
59+
It'll show red circles (🔴) for untouched pins and blue circles (🔵) for touched pins.
60+
61+
## Buying
62+
63+
* [Adafruit](https://www.adafruit.com/products/1602)
64+
65+
## Future plans
66+
67+
* Add support for calling `reset()` to reset the board via the Reset pin

bin/cap1188

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#!/usr/bin/env node
2+
3+
const readline = require('readline');
4+
5+
const connect = require('../').connect;
6+
7+
let hasLogged = false;
8+
9+
const logTouches = touches => {
10+
const moveCursorY = hasLogged ? -1 : 0;
11+
hasLogged = true;
12+
13+
readline.clearLine(process.stdout);
14+
readline.moveCursor(process.stdout, -touches.length, moveCursorY);
15+
16+
console.log(touches.map(t => (t ? '🔵' : '🔴')).join(' '));
17+
};
18+
19+
connect().then(cap1188 => {
20+
setInterval(() => logTouches(cap1188.readTouches()), 100);
21+
});

examples/cap1188-basic.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
const connect = require('../').connect;
2+
3+
// Connect to the CAP1188 breakout.
4+
// Returns a promise that resolves to the
5+
// CAP1188 instance when it's ready.
6+
const connectionPromise = connect();
7+
8+
// When it's ready, begin a loop to read
9+
// the touches
10+
connectionPromise.then(cap1188 => {
11+
setInterval(() => {
12+
// touches is an array of booleans
13+
// true means it's touched, false if not
14+
const touches = cap1188.readTouches();
15+
console.log(touches);
16+
}, 100);
17+
});

index.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
const init = require('raspi').init;
2+
const I2C = require('raspi-i2c').I2C;
3+
4+
const connect = require('./lib/CAP1188').connect;
5+
6+
module.exports.connect = ({ i2c = new I2C() } = {}) => {
7+
return new Promise((resolve, reject) => {
8+
init(() => {
9+
const cap1188 = connect(i2c);
10+
resolve(cap1188);
11+
});
12+
});
13+
};

lib/CAP1188.js

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
/* Copyright (c) 2018 Andrew Nicolaou. See the file LICENSE for copying permission. */
2+
/*
3+
Module for Adafruit CAP1188 8-Key Capacitive Touch Sensor Breakout
4+
Only I2C is supported.
5+
6+
See: https://www.adafruit.com/products/1602
7+
A port of the same library for Espruino:
8+
http://www.espruino.com/CAP1188
9+
*/
10+
var C = {
11+
ADDRESS_DEFAULT: 0x29
12+
};
13+
14+
/* Register addresses*/
15+
var R = {
16+
MAIN_CONTROL: 0x00,
17+
SENSOR_INPUT_STATUS: 0x03,
18+
MULTI_TOUCH_CONFIG: 0x2a,
19+
STANDBY_CONFIG: 0x41,
20+
SENSOR_INPUT_LINKING: 0x72,
21+
LED_OUTPUT_CONTROL: 0x74
22+
};
23+
24+
/* Bits within register for functions */
25+
var B = {
26+
MAIN_CONTROL_INT: 0x0
27+
};
28+
29+
function CAP1188(_i2c, _opts) {
30+
_opts = _opts == null ? {} : _opts;
31+
this.i2c = _i2c;
32+
33+
// Support old API where second param was _addr
34+
if (typeof _opts === 'number') {
35+
this.addr = _opts;
36+
} else {
37+
this.addr = _opts.address || C.ADDRESS_DEFAULT;
38+
this.resetPin = _opts.resetPin || null;
39+
}
40+
41+
this.initialize();
42+
}
43+
44+
/* Initialize the chip */
45+
CAP1188.prototype.initialize = function() {
46+
this.linkLedsToSensors();
47+
this.multipleTouches(true);
48+
// "Speed up a bit"
49+
// this.i2c.writeTo(this.addr, [R.STANDBY_CONFIG, 0x30]);
50+
this.i2c.writeSync(this.addr, R.STANDBY_CONFIG, Buffer.from([0x30]));
51+
};
52+
53+
/* Reset the chip if a reset pin has been specified */
54+
CAP1188.prototype.reset = function(callback) {
55+
throw new Error('Reset not currently supported');
56+
57+
var delay = 100,
58+
pin = this.resetPin,
59+
self = this;
60+
61+
if (pin == null) {
62+
throw new Error('CAP1188 reset called but no resetPin given');
63+
}
64+
65+
pin.write(0);
66+
setTimeout(function() {
67+
pin.write(1);
68+
setTimeout(function() {
69+
pin.write(0);
70+
setTimeout(function() {
71+
self.initialize();
72+
if (callback) {
73+
callback();
74+
}
75+
}, delay);
76+
}, delay);
77+
}, delay);
78+
};
79+
80+
/* How many simultaneous touches to allow */
81+
CAP1188.prototype.multipleTouches = function(enable) {
82+
// 1 will block multiple touches
83+
this.writeBit(R.MULTI_TOUCH_CONFIG, 7, enable ? 0 : 1);
84+
};
85+
86+
/* Link the LED to corresponding sensor */
87+
CAP1188.prototype.linkLedsToSensors = function() {
88+
for (var i = 0; i < 8; i++) {
89+
this.linkLedToSensor(i, 1);
90+
}
91+
};
92+
93+
/* Link LED pin to sensor */
94+
CAP1188.prototype.linkLedToSensor = function(num, enable) {
95+
this.writeBit(R.SENSOR_INPUT_LINKING, num, enable);
96+
};
97+
98+
/* Read state of all sensors */
99+
CAP1188.prototype.readTouches = function() {
100+
var touches = [],
101+
raw;
102+
103+
// this.i2c.writeTo(this.addr, R.SENSOR_INPUT_STATUS);
104+
this.i2c.writeSync(this.addr, Buffer.from([R.SENSOR_INPUT_STATUS]));
105+
106+
// raw = this.i2c.readFrom(this.addr, 1)[0];
107+
raw = this.i2c.readSync(this.addr, 1)[0];
108+
109+
if (raw) {
110+
// Clear interrupt to be able to read again
111+
this.writeBit(R.MAIN_CONTROL, B.MAIN_CONTROL_INT, 0);
112+
}
113+
114+
for (var i = 0; i < 8; i++) {
115+
touches[i] = this.getBit(raw, i);
116+
}
117+
118+
return touches;
119+
};
120+
121+
/* */
122+
CAP1188.prototype.getBit = function(byt, position) {
123+
return 1 == ((byt >> position) & 1);
124+
};
125+
126+
/* Set a single bit in a register */
127+
CAP1188.prototype.writeBit = function(reg, bit, val) {
128+
// this.i2c.writeTo(this.addr, reg);
129+
this.i2c.writeSync(this.addr, Buffer.from([reg]));
130+
131+
// var b = this.i2c.readFrom(this.addr, 1)[0];
132+
var b = this.i2c.readSync(this.addr, 1)[0];
133+
134+
b = val !== 0 ? b | (1 << bit) : b & ~(1 << bit);
135+
136+
// this.i2c.writeTo(this.addr, [reg, b]);
137+
this.i2c.writeSync(this.addr, reg, Buffer.from([b]));
138+
};
139+
140+
/* Set more bits in a register */
141+
CAP1188.prototype.writeBits = function(reg, shift, val) {
142+
// this.i2c.writeTo(this.addr, reg);
143+
this.i2c.writeSync(this.addr, Buffer.from([reg]));
144+
// var b = this.i2c.readFrom(this.addr, 1)[0];
145+
var b = this.i2c.readSync(this.addr, 1)[0];
146+
147+
b = b | (val << shift);
148+
// this.i2c.writeTo(this.addr, [reg, b]);
149+
this.i2c.writeSync(this.addr, reg, Buffer.from([b]));
150+
};
151+
152+
exports.connect = function(_i2c, _addr) {
153+
return new CAP1188(_i2c, _addr);
154+
};

package-lock.json

Lines changed: 71 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"name": "raspi-cap",
3+
"version": "0.0.1",
4+
"description":
5+
"Raspberry Pi / Node.js module for the CAP1188 capacitive touch breakout ",
6+
"main": "index.js",
7+
"bin": {
8+
"raspi-cap-debug": "./bin/cap1188"
9+
},
10+
"scripts": {
11+
"test": "echo \"Error: no test specified\" && exit 1"
12+
},
13+
"homepage": "https://github.com/andrewn/raspi-cap",
14+
"bugs": {
15+
"url": "https://github.com/andrewn/raspi-cap/issues"
16+
},
17+
"os": ["linux"],
18+
"keywords": ["raspberry pi", "cap1188", "touch"],
19+
"author": "Andrew Nicolaou <[email protected]>",
20+
"license": "Apache-2.0",
21+
"dependencies": {
22+
"raspi": "^5.0.2",
23+
"raspi-i2c": "^6.1.0"
24+
}
25+
}

0 commit comments

Comments
 (0)