-
• #3
Great! I'd love to see how you get on - let me know if you have any questions :)
The disc dispenser is something @JGreen laser cut (along with discs out of some bits of scrap) - I could probably find the drawings for you... The original plan was to use coloured ping-pong balls though, and you could make a great little feed for those out of 2 lengths of bent coat hanger (I've seen the MeArm lift ping-pong balls really well.
Only things I'd say to watch out for are:
- Decent power supply - Even with capacitors, it was really pushing it trying to power the Arm and lights off of USB - we used a bench supply in the end.
- The light sensor's great, but it gets thrown off by ambient light a lot. It'd be worth making a little black box with it in, so the only light it sees is what gets reflected from the ball/token/whatever.
- Decent power supply - Even with capacitors, it was really pushing it trying to power the Arm and lights off of USB - we used a bench supply in the end.
-
• #5
// Servo 0: base rotation // Servo 1: direct in/out movement // Servo 2: in/out movement via linkage // Servo 3: gripper // Servo pins var SERVOS = [C4,B15,B14,B13]; // Servo home pulse widths - tweak these for different arms (depending on assembly) var SERVOHOME = [1.51,1.5,1.5,1.5]; // gripper positions var JOPEN = 0; var JCLOSE = 0.45; // Keyframes for movement of arm. Each line // is a position, and we move between them // at 2fps // Pick up token, move it to the sensor var KF_PICKUP = [ [ 0, 0, 0, JOPEN ], // default position // [ 0, 0.3, -0.1, JOPEN ], [ 0, 0.25, -0.1, JOPEN ], [ 0, 0.45, -0.3, JOPEN ], // over token here [ 0, 0.45, -0.3, JCLOSE ], // over token here [ 0, 0.25, -0.1, JCLOSE ], [ 0, 0, 0, JCLOSE ], [ 0.75, -0.3, 0, JCLOSE ], // colour sensor here [ 0.75, -0.3, 0, JCLOSE ], ]; // Hold steady at the sensor var KF_TEST_RGB = [ // just hold steady for 2 secs [ 0.75, -0.3, 0, JCLOSE ], [ 0.75, -0.3, 0, JCLOSE ], [ 0.75, -0.3, 0, JCLOSE ], [ 0.75, -0.3, 0, JCLOSE ], [ 0.75, -0.3, 0, JCLOSE ], ]; // move from the sensor to a location, release gripper, go home var KF_DOWN_LEFT = [ [ 0.75, -0.3, 0, JCLOSE ], // colour sensor here [ 0.3, 0.45, -0.3, JCLOSE ], // down left [ 0.3, 0.45, -0.3, JOPEN ], [ 0, 0, 0, JOPEN ], // home [ 0, 0, 0, JOPEN ], ]; var KF_DOWN_RIGHT = [ [ 0.75, -0.3, 0, JCLOSE ], // colour sensor here [ -0.3, -0.3, 0, JCLOSE ], [ -0.3, 0.7, 0.0, JCLOSE ], // down left [ -0.3, 0.7, 0.0, JOPEN ], [ 0, 0, 0, JOPEN ], // home [ 0, 0, 0, JOPEN ], ]; var KF_DOWN_RIGHT_NEAR = [ [ 0.75, -0.3, 0, JCLOSE ], // colour sensor here [ -0.4, -0.3, 0, JCLOSE ], [ -0.4, -0.2, -0.4, JCLOSE ], [ -0.4, -0.2, -0.4, JOPEN ], // down left [ 0, 0, 0, JOPEN ], // home [ 0, 0, 0, JOPEN ], ]; // variables for keyframe movement var keyInterval; var keyPos = 0; var keyEnd = 0; var keyFrames = []; var keyCallback; var rgbAvr = [0,0,0]; // average RGB value var tcs; // rgb sensor var isRunning = false; // for on/off button var ledRGBs = new Uint8Array(25*3); // values for LED strip // Called to animate between keyframes function step() { keyPos += 0.04; // 20ms * 2fps var n = 0|keyPos; var a = keyPos-n; var n2 = n+1; //print(keyPos,n,n2,a); for (var i in SERVOS) { // interpolate between keyframes var p = keyFrames[n][i]*(1-a) + keyFrames[n2][i]*a; // move servo digitalPulse(SERVOS[i], 1, SERVOHOME[i]+p); } // are we finished? if (keyPos >= keyEnd) { clearInterval(keyInterval); keyInterval = undefined; if (keyCallback) keyCallback(); } } // Play back an array of keyframes, call callback when done function playback(frames, callback) { keyPos = 0 - 0.02; keyEnd = frames.length-2; keyFrames = frames; keyCallback = callback; keyInterval = setInterval(step, 20); } // Test a single token function testToken() { // pick it up playback(KF_PICKUP, function() { // then wait with it by the sensor for 2 secs playback(KF_TEST_RGB, function() { // print the colour values and work out if it's red, green or blue // finally put it down in the right place and start again print(rgbAvr); if (rgbAvr[0] > rgbAvr[1] && rgbAvr[0] > rgbAvr[2]) { // red print("Red!"); playback(KF_DOWN_LEFT, testToken); } else if (rgbAvr[1] > rgbAvr[0] && rgbAvr[1] > rgbAvr[2]) { // green print("Green!"); playback(KF_DOWN_RIGHT, testToken); } else { print("Blue!"); playback(KF_DOWN_RIGHT_NEAR, testToken); // blue } }); }); } // Get RGB value from the sensor function getRGB() { // get the value var v = tcs.getValue(); // re-scale it, to get full saturation and lightness (leaving just hue) var min = Math.min(v.red, v.green, v.blue); var range = Math.max(v.red, v.green, v.blue) - min; if (range<1) range=1; var rgb = [ // values between 0 and 255 (v.red - min)*200/range, // tweak red - so we don't accidentally classify green sometimes (v.green - min)*255/range, (v.blue - min)*255/range, ]; // handle the average rgbAvr[0] = rgbAvr[0]*0.9 + rgb[0]*0.1; rgbAvr[1] = rgbAvr[1]*0.9 + rgb[1]*0.1; rgbAvr[2] = rgbAvr[2]*0.9 + rgb[2]*0.1; // set the LED strip to the right colour for (var i=0;i<ledRGBs.length;i+=3) ledRGBs.set(rgbAvr,i); SPI1.send4bit(ledRGBs, 0b0001, 0b0011); } // Start the arm working - initialise RGB sensor and start movement function startArm() { SPI1.setup({baud:3200000, mosi:B5}); // LEDs I2C1.setup({scl:B8, sda:B9}); // RGB sensor tcs = require("TCS3472x").connect(I2C1, 1 /*integration cycles*/, 1 /*gain*/); testToken(); // start arm movement setTimeout(function() { // we seem to need a delay after initialisation before we use the RGB sensor setInterval(getRGB,20); },1000); } // On/off button setWatch(function() { if (!isRunning) { LED1.set(); isRunning = true; startArm(); } else { LED1.reset(); isRunning = false; clearInterval(); } }, BTN, {edge:"rising", repeat:true, debounce:50}); // For testing - call startTest() and then change the // values in the test array to work out the positions // needed for the keyframes array var test = [0,0,0,0]; function startTest() { setInterval(function() { for (var i in SERVOS) { digitalPulse(SERVOS[i], 1, SERVOHOME[i]+test[i]); } }, 20); } //startTest()
-
• #6
enter code here strong text
1 Attachment
-
• #7
Hi - please could you explain what you have posted up here? Is the JS code changes somehow? And what is the Arduino code for?
Me and @JGreen (@jsjgreen on Twitter) had a go at a demo for his GCSE Technology classes (for John Port School) yesterday - it's showing how a Microcontroller can use inputs to control outputs in order to do something useful...
https://youtu.be/Jxz2aHnxqpI
It's just a MeArm, Adafruit TCS34725, and one of the original Espruino boards...
And that's it - the arm just runs through a set of keyframes that are stored in an array that tell it how to move to pick up the token and place it in front of the sensor, and once the sensor has had time to average out the colour it then chooses from 1 of 3 sets of movements, which determine where the token is dropped.
Source code should be attached - it's a bit too big to inline, but mostly because of the comments!
Thanks to @DrAzzy for the TCS3472x module - docs for it will be on the website in the next day here
1 Attachment