├── .gitignore
├── README.md
├── bitcoinDonation.png
├── firmware
└── arduinoFirmware
│ ├── bitcoinMachine
│ └── bitcoinMachine.ino
│ ├── bitcoinMachineServo
│ └── bitcoinMachineServo.ino
│ └── bitcoinMachineServo5
│ └── bitcoinMachineServo5.ino
├── photo.jpg
└── server
└── BitRobot.js
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 |
5 | # Runtime data
6 | pids
7 | *.pid
8 | *.seed
9 |
10 | # Directory for instrumented libs generated by jscoverage/JSCover
11 | lib-cov
12 |
13 | # Coverage directory used by tools like istanbul
14 | coverage
15 |
16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
17 | .grunt
18 |
19 | # node-waf configuration
20 | .lock-wscript
21 |
22 | # Compiled binary addons (http://nodejs.org/api/addons.html)
23 | build/Release
24 |
25 | # Dependency directory
26 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
27 | node_modules
28 |
29 | public/content/images
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # BitRobot
2 | This makes your arduino do stuff when a bitcoin transaction happens. It is useful for building bitcoin accepting vending machines, doors or any robot that wants to earn a living.
3 |
4 | 
5 |
6 | # Howto
7 |
8 | You'll need the [aJson arduino library](https://github.com/interactive-matter/aJson)
9 |
10 | Upload _firmware/arduinoFirmware/bitcoinMachine_ to the arduino, see the pins I use in the code.
11 |
12 |
13 | Next you'll need node.js and some modules:
14 |
15 | ```
16 | //install modules using npm
17 | cd server
18 | npm install ws
19 | npm install serialport
20 | npm install json-scrape
21 | npm install moment
22 |
23 | //run the server that listens to the blockchain and tells the arduino what to do
24 | node BitRobot.js
25 | ```
26 |
27 | # Bitcoin donation
28 |
29 | If you like it please consider sending me some bitcoin this encourages me to build and share more. I'm also open to collaboration, so you can email me on [rouan@8bo.org](mailto:rouan@8bo.org)
30 |
31 | 
32 | 1EZ6S8YqfxzfMKCCtpzKeEJW1qMthQnCuD
33 |
34 |
--------------------------------------------------------------------------------
/bitcoinDonation.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rvdende/BitRobot/343214f444793e0d2e4c7a6d215403a789c74a27/bitcoinDonation.png
--------------------------------------------------------------------------------
/firmware/arduinoFirmware/bitcoinMachine/bitcoinMachine.ino:
--------------------------------------------------------------------------------
1 | #include
2 | aJsonStream serial_stream(&Serial);
3 |
4 | void setup(void) {
5 | Serial.begin(9600);
6 | pinMode(13, OUTPUT); //dir1
7 | pinMode(12, OUTPUT); //step1
8 | pinMode(7, OUTPUT); //enable1
9 | pinMode(11, OUTPUT); //dir2
10 | pinMode(10, OUTPUT); //step2
11 | pinMode(6, OUTPUT); //enable1
12 | }
13 |
14 | void loop(void) {
15 | //powerdown motors
16 | digitalWrite(7, 1);
17 | digitalWrite(6, 1);
18 |
19 | //recieve commands
20 | while (serial_stream.available())
21 | {
22 | aJsonObject *msg = aJson.parse(&serial_stream);
23 | processMessage(msg); //see api.ino
24 | aJson.deleteItem(msg);
25 | }
26 | delay(10); //just here to slow down the output so it is easier to read
27 | }
28 |
29 |
30 | /* ==================================================================
31 | Expects something like this over serial:
32 |
33 | {"led": "0.1"}
34 | {"led": "1.0"}
35 | */
36 |
37 | void processMessage(aJsonObject *msg)
38 | {
39 |
40 | aJsonObject *led = aJson.getObjectItem(msg, "led");
41 | if (led) {
42 | char* ledvaluestring = led->valuestring;
43 | float ledvaluefloat = atof(ledvaluestring);
44 | int ledvalueint = ledvaluefloat;
45 | digitalWrite(13, ledvalueint);
46 | }
47 |
48 | aJsonObject *c = aJson.getObjectItem(msg, "buy");
49 | if (c)
50 | {
51 | char* d = c->valuestring;
52 | float b = atof(d);
53 | int i = b;
54 |
55 | if (i == 1) {
56 | //stepper motor
57 | for (int n = 0; n < 10000; n++) {
58 | digitalWrite(7, 0); //enable motor
59 | digitalWrite(12, 0);
60 | delayMicroseconds(100);
61 | digitalWrite(12, 1);
62 | delayMicroseconds(100);
63 | }
64 | }
65 |
66 | if (i == 2) {
67 | //stepper motor
68 | for (int n = 0; n < 10000; n++) {
69 | digitalWrite(6, 0); //enable motor
70 | digitalWrite(10, 0);
71 | delayMicroseconds(100);
72 | digitalWrite(10, 1);
73 | delayMicroseconds(100);
74 | }
75 | }
76 |
77 | if (i == 3) {
78 | digitalWrite(11, 1);
79 | delay(5000);
80 | digitalWrite(11, 0);
81 | }
82 | }
83 |
84 | }
85 |
--------------------------------------------------------------------------------
/firmware/arduinoFirmware/bitcoinMachineServo/bitcoinMachineServo.ino:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | aJsonStream serial_stream(&Serial);
5 | Servo myservo;
6 |
7 | int pos = 0;
8 |
9 | void setup(void) {
10 | Serial.begin(9600);
11 | myservo.attach(9);
12 | }
13 |
14 | void loop(void) {
15 | //recieve commands
16 | while (serial_stream.available())
17 | {
18 | aJsonObject *msg = aJson.parse(&serial_stream);
19 | processMessage(msg); //see api.ino
20 | aJson.deleteItem(msg);
21 | }
22 | delay(10); //just here to slow down the output so it is easier to read
23 | }
24 |
25 |
26 | /* ==================================================================
27 | Expects something like this over serial:
28 |
29 | {"buy": "1.0"}
30 | */
31 |
32 | void processMessage(aJsonObject *msg)
33 | {
34 | aJsonObject *c = aJson.getObjectItem(msg, "buy");
35 | if (c)
36 | {
37 | char* d = c->valuestring;
38 | float b = atof(d);
39 | int i = b;
40 |
41 | if (i == 1) {
42 | //stepper motor
43 | moveServo();
44 | }
45 |
46 | }
47 |
48 | }
49 |
50 | void moveServo() {
51 | for(pos = 0; pos <= 180; pos += 1) // goes from 0 degrees to 180 degrees
52 | { // in steps of 1 degree
53 | myservo.write(pos); // tell servo to go to position in variable 'pos'
54 | delay(15); // waits 15ms for the servo to reach the position
55 | }
56 | for(pos = 180; pos>=0; pos-=1) // goes from 180 degrees to 0 degrees
57 | {
58 | myservo.write(pos); // tell servo to go to position in variable 'pos'
59 | delay(15); // waits 15ms for the servo to reach the position
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/firmware/arduinoFirmware/bitcoinMachineServo5/bitcoinMachineServo5.ino:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | aJsonStream serial_stream(&Serial);
5 | Servo myservoA;
6 | Servo myservoB;
7 | Servo myservoC;
8 | Servo myservoD;
9 | Servo myservoE;
10 |
11 | int pos = 0;
12 |
13 | void setup(void) {
14 | Serial.begin(9600);
15 | //might have to change pin numbers to be sure they can do PWM
16 | myservoA.attach(9);
17 | myservoB.attach(8);
18 | myservoC.attach(7);
19 | myservoD.attach(6);
20 | myservoE.attach(5);
21 | }
22 |
23 | void loop(void) {
24 | //recieve commands
25 | while (serial_stream.available())
26 | {
27 | aJsonObject *msg = aJson.parse(&serial_stream);
28 | processMessage(msg); //see api.ino
29 | aJson.deleteItem(msg);
30 | }
31 | delay(10); //just here to slow down the output so it is easier to read
32 | }
33 |
34 |
35 | /* ==================================================================
36 | Expects something like this over serial:
37 | {"buy": "1.0"}
38 | */
39 |
40 | void processMessage(aJsonObject *msg)
41 | {
42 | aJsonObject *c = aJson.getObjectItem(msg, "buy");
43 | if (c)
44 | {
45 | char* d = c->valuestring;
46 | float b = atof(d);
47 | int i = b;
48 |
49 | if (i == 1) { moveServoA(); }
50 | if (i == 2) { moveServoB(); }
51 | if (i == 3) { moveServoC(); }
52 | if (i == 4) { moveServoD(); }
53 | if (i == 5) { moveServoE(); }
54 |
55 | }
56 |
57 | }
58 |
59 | void moveServoA() {
60 | for(pos = 0; pos <= 180; pos += 1) // goes from 0 degrees to 180 degrees
61 | { // in steps of 1 degree
62 | myservoA.write(pos); // tell servo to go to position in variable 'pos'
63 | delay(15); // waits 15ms for the servo to reach the position
64 | }
65 | for(pos = 180; pos>=0; pos-=1) // goes from 180 degrees to 0 degrees
66 | {
67 | myservoA.write(pos); // tell servo to go to position in variable 'pos'
68 | delay(15); // waits 15ms for the servo to reach the position
69 | }
70 | }
71 |
72 | void moveServoB() {
73 | for(pos = 0; pos <= 180; pos += 1) // goes from 0 degrees to 180 degrees
74 | { // in steps of 1 degree
75 | myservoB.write(pos); // tell servo to go to position in variable 'pos'
76 | delay(15); // waits 15ms for the servo to reach the position
77 | }
78 | for(pos = 180; pos>=0; pos-=1) // goes from 180 degrees to 0 degrees
79 | {
80 | myservoB.write(pos); // tell servo to go to position in variable 'pos'
81 | delay(15); // waits 15ms for the servo to reach the position
82 | }
83 | }
84 |
85 | void moveServoC() {
86 | for(pos = 0; pos <= 180; pos += 1) // goes from 0 degrees to 180 degrees
87 | { // in steps of 1 degree
88 | myservoC.write(pos); // tell servo to go to position in variable 'pos'
89 | delay(15); // waits 15ms for the servo to reach the position
90 | }
91 | for(pos = 180; pos>=0; pos-=1) // goes from 180 degrees to 0 degrees
92 | {
93 | myservoC.write(pos); // tell servo to go to position in variable 'pos'
94 | delay(15); // waits 15ms for the servo to reach the position
95 | }
96 | }
97 |
98 | void moveServoD() {
99 | for(pos = 0; pos <= 180; pos += 1) // goes from 0 degrees to 180 degrees
100 | { // in steps of 1 degree
101 | myservoD.write(pos); // tell servo to go to position in variable 'pos'
102 | delay(15); // waits 15ms for the servo to reach the position
103 | }
104 | for(pos = 180; pos>=0; pos-=1) // goes from 180 degrees to 0 degrees
105 | {
106 | myservoD.write(pos); // tell servo to go to position in variable 'pos'
107 | delay(15); // waits 15ms for the servo to reach the position
108 | }
109 | }
110 |
111 | void moveServoE() {
112 | for(pos = 0; pos <= 180; pos += 1) // goes from 0 degrees to 180 degrees
113 | { // in steps of 1 degree
114 | myservoE.write(pos); // tell servo to go to position in variable 'pos'
115 | delay(15); // waits 15ms for the servo to reach the position
116 | }
117 | for(pos = 180; pos>=0; pos-=1) // goes from 180 degrees to 0 degrees
118 | {
119 | myservoE.write(pos); // tell servo to go to position in variable 'pos'
120 | delay(15); // waits 15ms for the servo to reach the position
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/photo.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rvdende/BitRobot/343214f444793e0d2e4c7a6d215403a789c74a27/photo.jpg
--------------------------------------------------------------------------------
/server/BitRobot.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | // npm install ws
4 | // npm install serialport
5 | // npm install json-scrape
6 | // npm install moment
7 |
8 | // Sources:
9 | // http://momentjs.com
10 | // https://github.com/websockets/ws
11 | // https://blockchain.info/api/api_websocket
12 |
13 |
14 | var moment = require('moment');
15 | var WebSocket = require('ws');
16 | var ready = 0;
17 |
18 | var listenws = function () {
19 |
20 |
21 | console.log(moment().format()+" Connecting to blockchain...")
22 | var bcsource = 'wss://ws.blockchain.info/inv';
23 | var ws = new WebSocket(bcsource);
24 |
25 | ws.on('open', function open() {
26 | console.log(moment().format()+' Blockchain source connected '+bcsource);
27 | ws.send('{"op":"addr_sub", "addr":"17Zu18pDzCneyt5Q7rFC3hjA6ysVoDGX6p"}');
28 | ws.send('{"op":"addr_sub", "addr":"1DNhNdGxZrnjDR6ydxWqm2Qe52NDVuk2QX"}');
29 |
30 | //ws.send('{"op":"unconfirmed_sub"}') //all
31 |
32 | });
33 |
34 |
35 | ws.on('message', function(indata, flags) {
36 | // flags.binary will be set if a binary data is received.
37 | // flags.masked will be set if the data was masked.
38 |
39 |
40 |
41 |
42 | var data = JSON.parse(indata);
43 |
44 | if (ready == 1) {
45 | console.log(data.x);
46 | for (var i in data.x.out) {
47 | if (data.x.out[i].addr == "17Zu18pDzCneyt5Q7rFC3hjA6ysVoDGX6p") {
48 | var apimsg = { "buy" : "1.0" };
49 | var apimsgstr = JSON.stringify(apimsg);
50 | arduino.write(apimsgstr);
51 | }
52 |
53 | if (data.x.out[i].addr == "1DNhNdGxZrnjDR6ydxWqm2Qe52NDVuk2QX") {
54 | var apimsg = { "buy" : "2.0" };
55 | var apimsgstr = JSON.stringify(apimsg);
56 | arduino.write(apimsgstr);
57 | }
58 | }
59 | }
60 |
61 |
62 | });
63 |
64 | ws.on('close', function close() {
65 | console.log(moment().format()+' Blockchain connection closed...');
66 | listenws();
67 | });
68 | }
69 |
70 | listenws();
71 |
72 | /* ====================================== */
73 |
74 | var SerialPort = require("serialport"); // so we can access the serial port
75 | var scraper = require('json-scrape')(); // cleans messy serial messages.
76 |
77 | var arduino;
78 |
79 | //LIST DEVICES/AUTODETECT
80 | SerialPort.list( function (err, ports) {
81 | console.log(moment().format()+" Autodetecting Arduino devices...")
82 | for (var num in ports) {
83 | console.log(ports[num]);
84 | if (ports[num].serialNumber == '754393336353517030D1') {
85 | console.log(moment().format()+" Arduino detected on "+ports[num].comName)
86 | arduino = new SerialPort.SerialPort(ports[num].comName, {baudrate: 9600}); //you must set the port and baudrate
87 | arduConnect(arduino);
88 | }
89 | }
90 | });
91 |
92 |
93 | var arduConnect = function (device) {
94 | ready = 1;
95 | device.on("data", datahandler);
96 | }
97 |
98 | var datahandler = function (data) {
99 | scraper.write(data);
100 | }
101 |
102 | scraper.on('data', function (data) {
103 | console.log(data)
104 | //io.sockets.emit("arduino", data)
105 | });
106 |
107 |
108 | /*
109 | // TO SEND TO ARDUINO
110 | // ideally this will be called from the browser event with socket io.
111 | // more in a later class on this.
112 | var data = { brightness: "0.1" }
113 | var test = JSON.stringify(data) // turns into string to send
114 | console.log(test)
115 | arduino.write(test)
116 | */
117 |
118 |
--------------------------------------------------------------------------------