├── .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 | ![alt tag](https://raw.githubusercontent.com/fluentart/BitRobot/master/photo.jpg) 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 | ![alt tag](https://raw.githubusercontent.com/fluentart/BitRobot/master/bitcoinDonation.png)
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 | --------------------------------------------------------------------------------