Skip to content

Modular-Things

This page is based on Quentin’s Bhutan WS
Ref. https://gitlab.fabcloud.org/pub/project/fab23

Note

This is original modular-things repo
Ref. https://github.com/modular-things/modular-things

Board

Quentin’s PCB

Alt text

My board

S4B-XH-SM4-TB


ATTENTION! The orientation of the H bridge is 180 degrees different.
Download Fusion360 Electronics file Download Library
XiaoRP2040_SMD_vertical_pinsocket
TB67H45FNG-FAB
S4B-XH-SM4_FAB

Pinheader & 0 ohm x1


ATTENTION! The orientation of the H bridge is 180 degrees different.
Download Eagle file brd/sch Download Eagle Lib XIAO_SMD-Pin.lbr

BOM

Part Count (ver1.0) Count (ver1.1) Info
Xiao RP2040 1 1
H-Bridge TB67H451FNG 2 2 TB67H450FNG is used here in ver 1.0
0.1uF 1206 2 2
1uF 1206 2 2
10uF 1206 2 2
0.25R 1206 2 2
120R 1206 2 2
0R 1206 1 -
1x7 SMD Vertical Pinsocket 2 2
1x4 SMD Pinheader 1 -
S4B-XH-SM4-TB
or 1x4 SMD Pinheader
- 1
1x2 SMD Pinheader 1 1

Arduino Code for Xiao RP2040

OSAP library

  • https://github.com/jakeread/osap-arduino -> Code -> Download ZIP
  • Include Library -> Add .ZIP Library

Board Manager

  • Ref. Earle F. Philhower, the Third’s PICO build

  • Additional Boards Manager URLs: https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json

  • Tools->Boards->Board Manager
    Type “pico” in the search box and select “Add”: Rp2040

Code

  • Repo
    • https://gitlab.fabcloud.org/pub/project/fab23/machine_workshop/-/tree/main/code/stepper-hbridge-rp2040?ref_type=heads
  • from this site

Update_after_bhutan_ws

  • Repo
    • https://github.com/modular-things/modular-things/tree/main/things/stepper-hbridge-xiao
      .  
      ├── firmware  
      │   └── simple-stepper  
      │       ├── motionStateMachine.cpp  
      │       ├── motionStateMachine.h  
      │       ├── simple-stepper.ino  
      │       ├── stepperDriver.cpp  
      │       └── stepperDriver.h  
      
      Pin Assign in stepperDriver.cpp
      #define AIN1_PIN 7//6
      #define AIN2_PIN 0//7
      #define BIN1_PIN 2//28
      #define BIN2_PIN 4//4
      #define APWM_PIN 6//27
      #define BPWM_PIN 3//29
      
      Open
      simple-stepper.ino

machine_workshop-main-code-stepper-hbridge-rp2040 % tree
.
└── code
    └── stepper-hbridge-rp2040
        ├── motionStateMachine.cpp
        ├── motionStateMachine.h
        ├── stepper-hbridge-rp2040.ino
        ├── stepperDriver.cpp
        └── stepperDriver.h
Open stepper-hbridge-rp2040.ino from ArduinoIDE and Upload it.

Pin Assign

Pin Assign
stepperDriver.cpp #define APWM_PIN 6
#define AIN1_PIN 7
#define AIN2_PIN 0

#define BPWM_PIN 3
#define BIN1_PIN 2
#define BIN2_PIN 4
Schematic
Xiao RP2040 Pinout

Modular Things Web UI

Important

Only Google Chrome base browser can use the Web serial

  • https://modular-things.github.io/modular-things/

Set up local server (This doesn’t work in my case)

install node.js

% node  --version  
v19.8.1
if not installed or < v16.15.1, download a installer from https://nodejs.org/ja/download/current

Clone Modular-Things repository and run

% pwd
/Users/yuichi
% mkdir repos
% ls
repos
% cd repos
% git clone https://github.com/modular-things/modular-things.git
% ls
modular-things
% cd modular-things
% npm install
% npm run dev
> sprig-3@1.0.0 dev
> astro dev
  🚀  astro  v2.0.4 started in 28ms
  ┃ Local    http://localhost:3000/modular-things/
  ┃ Network  use --host to expose
Open http://localhost:3000/modular-things/ in browser

Note: Ctr+C to stop npm running

Connecting Things(Xiao) to UI

Connect Xiao to PC

Press pair new thing -> select Serial port -> XIAO RP2040
The available Javascript properties are displayed on the right. If not, press scan and it will appear
Alt text

Press rename to name your “Things”(board)
This name will be used as javascript object name
Alt text

Open browser’s DevTools console with

  • cmd + shift + j (Linux)
  • ctrl + shift + j (win)
  • command + option + j (mac)

Alt text

JavaScript

Examples from Instructor Bootcamp Waag

/* 
//----------------------------------------------------------------Example1
//stepperBabken 
//http://academany.fabcloud.io/fabacademy/2023/instructors-bootcamp/Projects/useless_machines2.0/

async function main() {
  await yuichiStepper.setCurrentScale(.8)
  await yuichiStepper.setStepsPerUnit(200)

  for (let i = 0; i < 20; i++) {
    // await yuichiStepper.setVelocity(Math.random()*300)
    await yuichiStepper.relative(1+i/100);
    await yuichiStepper.relative(-(1+i/100));
    await delay(1000)

  }
}

function delay(time) {
  return new Promise(resolve => setTimeout(resolve, time));
}

main()
*/


/* 
//----------------------------------------------------------------Example2
//Waag Bootcamp by Quention
yuichiStepper.setCurrentScale(1);
yuichiStepper.setStepsPerUnit(200);
yuichiStepper.setVelocity(900);
//yuichiStepper.setAccel(500);

async function main(){
  let pos = 0;

  for (let i=0; i<6; i++){
    pos = pos ==0 ?-850:0;
    await yuichiStepper.absolute(pos);
  }
}

main();
*/

/*
//----------------------------------------------------------------Example3
//Waag Bootcamp by Quention
async function main(){
  await yuichiStepper.setCurrentScale(0.8);
  await yuichiStepper.setStepsPerUnit(200);
  await yuichiStepper.setAccel(10);
  await yuichiStepper.setVelocity(20);
  await yuichiStepper.absolute(5);
  await yuichiStepper.absolute(0);
  await yuichiStepper.absolute(5);
  await yuichiStepper.absolute(0);  
}

main();
*/

Stepper Motor

42BYGH37 From Inventory

Ref. amazon.com Alt text Alt text

my code for Liner Axis

yuichiStepper.setCurrent(0.8);//0.8 or 1
yuichiStepper.setStepsPerUnit(8);//1-7 slower, 8 fast, >9 no work
yuichiStepper.setAccel(2000); //<50 no work, 60-100 slow, 400-1000 quick, 2000 very quick
//yuichiStepper.setMaxVelocity(100);//0-1000 same. Need??

//yuichiStepper.velocity(1000);
//yuichiStepper.setPosition();
//yuichiStepper.setMaxAccel(100);
//yuichiStepper.setMaxVelocity(100);


async function main(){
  let pos = 0;

  for (let i=0; i<2; i++){
    console.log("i="+i);//Open console with command + option + j (mac)
    pos = pos ==0 ? 180:0; //move 0 to 180 CW, move back 180 to 0 CCW
    console.log("pos="+pos);
    await yuichiStepper.absolute(pos);
  }
  //yuichiStepper.setCurrent(0);
  //stop();
}

main();

/*
StepperMoter 42BYGH37
A1_A2,     B1_B2 (Left to Right)
BLK_GRN, RED_BLU
*/

my code for CoreXY

yuichiStepper.setCurrent(0.8);//0.8 or 1
yuichiStepper.setStepsPerUnit(4);//4 for CoreXY, 1-7 slower, 8 fast, >9 no work
yuichiStepper.setAccel(1000); //<50 no work, 60-100 slow, 400-1000 quick, 2000 very quick

LeonStepper.setCurrent(0.8);//0.8 or 1
LeonStepper.setStepsPerUnit(4);//4 for CoreXY, 1-7 slower, 8 fast, >9 no work
LeonStepper.setAccel(1000); //<50 no work, 60-100 slow, 400-1000 quick, 2000 very quick


async function main(){
  let pos = 0;

  for (let i=0; i<2; i++){
    console.log("i="+i);//Open console with command + option + j (mac)
    pos = pos ==0 ? 90:0; //move 0 to 180 CW, move back 180 to 0 CCW
    console.log("pos="+pos);
    await yuichiStepper.absolute(pos);
    await LeonStepper.absolute(pos);
  }
  //yuichiStepper.setCurrent(0);
  //stop();
}

main();

/*
StepperMoter 42BYGH37
A1_A2,     B1_B2 (Left to Right)
BLK_GRN, RED_BLU
*/

//yuichiStepper.setMaxVelocity(100);//0-1000 same. Need??
//yuichiStepper.velocity(1000);
//yuichiStepper.setPosition();
//yuichiStepper.setMaxAccel(100);
//yuichiStepper.setMaxVelocity(100);

JK42HS34-1334AC

Ref. data sheet

My Code 1

yuichiStepper.setCurrentScale(0.8);
yuichiStepper.setStepsPerUnit(200);
yuichiStepper.setVelocity(12);//stable value: 11,12,13
yuichiStepper.setAccel(500);

async function main(){
  let pos = 0;

  for (let i=0; i<2; i++){
    console.log("i="+i);
    pos = pos ==0 ?-300:0;
    console.log("pos="+pos);
    await yuichiStepper.absolute(pos);
  }
  yuichiStepper.setCurrentScale(0);
}

main();


/*
A1A2 B1B2

RY BG
-100 ->CCW
0 ->CW

YR BG
-100 ->CW
0 ->CCW

YR GB
-100 ->CCW
0 -> CW

RY GB
-100 ->CW
0 -> CCW

*/

My Code 2

yuichiStepper.setCurrentScale(0.8);
yuichiStepper.setStepsPerUnit(200);
yuichiStepper.setVelocity(12);//max is 20, but stable when 12,13
yuichiStepper.setAccel(500);

async function main(){
  let pos = 0;

  for (let i=0; i<2; i++){
    console.log("i="+i);//Open console with command + option + j (mac)
    pos = pos ==0 ? 100:0; //move 0 to 100 CW, move back 100 to 0 CCW
    console.log("pos="+pos);
    await yuichiStepper.absolute(pos);
  }
  yuichiStepper.setCurrentScale(0);//Stop current to stop vibration
}

main();


/*
A1_A2, B1_B2 (Left to Right)

RED_BLU, BLK_GRN
100 ->CW
0 ->CWW
*/

Hardware

Liner Axis

Based on https://gitlab.fabcloud.org/pub/project/fab23

amount REF Description
Motor side
4 M5x10 sockethead screw
4 T-nut M5
1 M5x30 sockethead screw
2 M5 washer
1 M5 spring nut
1 M5 nut
4 M3x8 sockethead screw
2 M3x30 +
1 M3 nut
1 M3x10 setscrew
2 625ZZ Bearing
Pulley side
2 M5x10 sockethead screw
2 M5x15 sockethead screw
1 M5x20 sockethead screw
4 T-nut M5
1 M5 nut
2 M5 washer
1 M5 spring nut
1 625ZZ Bearing
Stage
4 V-wheel
4 M5x30 sockethead screw
4 M5 nut
4 M5 washer
4 M5 spring nut
Other
1 600mm aluminum extrusion
1 Nema17 Stepper motor 5V
1 thread no-extention fishing line

3D parts and Laser cut part

Later

Code for CoreXY With UI

import confetti from 'https://cdn.skypack.dev/canvas-confetti';

confetti();

yuichiStepper.setCurrent(0.8);//0.8 or 1
yuichiStepper.setStepsPerUnit(4);//4 for CoreXY, 1-7 slower, 8 fast, >9 no work
yuichiStepper.setAccel(1000); //<50 no work, 60-100 slow, 400-1000 quick, 2000 very quick

LeonStepper.setCurrent(0.8);//0.8 or 1
LeonStepper.setStepsPerUnit(4);//4 for CoreXY, 1-7 slower, 8 fast, >9 no work
LeonStepper.setAccel(1000); //<50 no work, 60-100 slow, 400-1000 quick, 2000 very quick


async function move(){
  let pos = 0;

  for (let i=0; i<2; i++){
    console.log("i="+i);//Open console with command + option + j (mac)
    pos = pos ==0 ? 90:0; //move 0 to 180 CW, move back 180 to 0 CCW
    console.log("pos="+pos);
    await yuichiStepper.absolute(pos);
    await LeonStepper.absolute(pos);
  }
  //yuichiStepper.setCurrent(0);
  //stop();
}

/*
StepperMoter 42BYGH37
A1_A2,     B1_B2 (Left to Right)
BLK_GRN, RED_BLU
*/

//yuichiStepper.setMaxVelocity(100);//0-1000 same. Need??
//yuichiStepper.velocity(1000);
//yuichiStepper.setPosition();
//yuichiStepper.setMaxAccel(100);
//yuichiStepper.setMaxVelocity(100);


const el = document.createElement("div");

el.style = `
  padding: 10px;
`

el.innerHTML = `
  <div>hello world!</div>
  <button>press this</button>
`;

el
  .querySelector("button")
  .addEventListener("click", () => {
    confetti();
    move()
  })

render(el);
import confetti from 'https://cdn.skypack.dev/canvas-confetti';


confetti();

yuichiStepper.setCurrent(0.8);//0.8 or 1
yuichiStepper.setStepsPerUnit(4);//4 for CoreXY, 1-7 slower, 8 fast, >9 no work
yuichiStepper.setAccel(1000); //<50 no work, 60-100 slow, 400-1000 quick, 2000 very quick

LeonStepper.setCurrent(0.8);//0.8 or 1
LeonStepper.setStepsPerUnit(4);//4 for CoreXY, 1-7 slower, 8 fast, >9 no work
LeonStepper.setAccel(1000); //<50 no work, 60-100 slow, 400-1000 quick, 2000 very quick


async function move(){
  let pos = 0;

  for (let i=0; i<2; i++){
    console.log("i="+i);//Open console with command + option + j (mac)
    pos = pos ==0 ? 90:0; //move 0 to 180 CW, move back 180 to 0 CCW
    console.log("pos="+pos);
    await yuichiStepper.absolute(pos);
    await LeonStepper.absolute(pos);
  }
  //yuichiStepper.setCurrent(0);
  //stop();
}

async function slide(value){
  let pos = 0;
  for (let i=0; i<2; i++){
    console.log("i="+i);//Open console with command + option + j (mac)
    pos = value
    console.log("pos="+pos);
    await LeonStepper.absolute(pos);
    await yuichiStepper.absolute(pos);
  }

}



const el = document.createElement("div");


el.style = `
  padding: 10px;
`

el.innerHTML = `
  <div>hello world!</div>
  <button>press this</button>

  <div>Slider</div>
  <input type="range" min="1" max="100" value="50" id="rangeSlider">
  <p>Value: <span id="rangeValue"></span></p>
`;

el
  .querySelector("button")
  .addEventListener("click", () => {
    confetti();
    move()
  })

const rangeSlider = el.querySelector("#rangeSlider");
const rangeValue = el.querySelector("#rangeValue");

rangeSlider.addEventListener("input", (event) => {
  const value = event.target.value;
  rangeValue.textContent = value;
  slide(value);

});


render(el);
import confetti from 'https://cdn.skypack.dev/canvas-confetti';


confetti();

yuichiStepper.setCurrent(0.8);//0.8 or 1
yuichiStepper.setStepsPerUnit(4);//4 for CoreXY, 1-7 slower, 8 fast, >9 no work
yuichiStepper.setAccel(1000); //<50 no work, 60-100 slow, 400-1000 quick, 2000 very quick

LeonStepper.setCurrent(0.8);//0.8 or 1
LeonStepper.setStepsPerUnit(4);//4 for CoreXY, 1-7 slower, 8 fast, >9 no work
LeonStepper.setAccel(1000); //<50 no work, 60-100 slow, 400-1000 quick, 2000 very quick


async function move(){
  let pos = 0;

  for (let i=0; i<2; i++){
    console.log("i="+i);//Open console with command + option + j (mac)
    pos = pos ==0 ? 90:0; //move 0 to 180 CW, move back 180 to 0 CCW
    console.log("pos="+pos);
    await yuichiStepper.absolute(pos);
    await LeonStepper.absolute(pos);
  }
  //yuichiStepper.setCurrent(0);
  //stop();
}

async function slide(value){
  let pos = 0;

  for (let i=0; i<2; i++){
    pos = value;
    await yuichiStepper.absolute(pos);
    await LeonStepper.absolute(-pos);
  }


  //await LeonStepper.absolute(value);
  //await yuichiStepper.absolute(-value);
  //for (let i=0; i<2; i++){
    //console.log("i="+i);//Open console with command + option + j (mac)
    //pos = value
    //console.log("pos="+pos);
    //await LeonStepper.absolute(pos);
    //await yuichiStepper.absolute(pos);
  //}

}



const el = document.createElement("div");


el.style = `
  padding: 10px;
`

el.innerHTML = `
  <div>hello world!</div>
  <button>press this</button>

  <div>Slider</div>
  <input type="range" min="1" max="100" value="50" id="rangeSlider">
  <p>Value: <span id="rangeValue"></span></p>
`;

el
  .querySelector("button")
  .addEventListener("click", () => {
    confetti();
    move()
  })

const rangeSlider = el.querySelector("#rangeSlider");
const rangeValue = el.querySelector("#rangeValue");

rangeSlider.addEventListener("input", (event) => {
  const value = event.target.value;
  rangeValue.textContent = value;
  slide(value);

});


render(el);
yuichiStepper.setCurrent(0.8);//0.8 or 1
yuichiStepper.setStepsPerUnit(1);//4 for CoreXY, 1-7 slower, 8 fast, >9 no work
yuichiStepper.setAccel(1000); //<50 no work, 60-100 slow, 400-1000 quick, 2000 very quick

LeonStepper.setCurrent(0.8);//0.8 or 1
LeonStepper.setStepsPerUnit(1);//4 for CoreXY, 1-7 slower, 8 fast, >9 no work
LeonStepper.setAccel(1000); //<50 no work, 60-100 slow, 400-1000 quick, 2000 very quick

const machine = createSynchronizer([yuichiStepper, LeonStepper]);

machine.setPosition([0, 0]);
console.log("pos1 "+await machine.getPosition());

async function slideY(valueY){
    console.log(valueY);
    await machine.absolute([valueY, valueY]);
console.log("pos"+await machine.getPosition());
}

async function slideX(valueX){
    console.log(valueX);
    await machine.absolute([valueX, -valueX]);
console.log("pos"+await machine.getPosition());
}

console.log("pos3 "+await machine.getPosition());

async function move(){
  let pos = 1;
    await yuichiStepper.absolute(pos);
    await LeonStepper.absolute(pos);
}
//}




const el = document.createElement("div");

el.style = `
  padding: 10px;
`

el.innerHTML = `
  <button>press this</button>
  <div>Y-Axis Slider</div>
  <input type="range" min="1" max="100" value="50" id="rangeSliderY">
  <p>Value: <span id="rangeValueY"></span></p>

  <div>X-Axis Slider</div>
  <input type="range" min="1" max="100" value="50" id="rangeSliderX">
  <p>Value: <span id="rangeValueX"></span></p>
`;

const rangeSliderY = el.querySelector("#rangeSliderY");
const rangeValueY = el.querySelector("#rangeValueY");

rangeSliderY.addEventListener("input", (event) => {
  const valueY = event.target.value;
  rangeValueY.textContent = valueY;
  slideY(valueY); 
});

const rangeSliderX = el.querySelector("#rangeSliderX");
const rangeValueX = el.querySelector("#rangeValueX");

rangeSliderX.addEventListener("input", (event) => {
  const valueX = event.target.value;
  rangeValueX.textContent = valueX;
  slideX(valueX);
});

el
  .querySelector("button")
  .addEventListener("click", () => {
    move()
})




render(el);
yuichiStepper.setCurrent(0.8);//0.8 or 1
yuichiStepper.setStepsPerUnit(1);//4 for CoreXY, 1-7 slower, 8 fast, >9 no work
yuichiStepper.setAccel(1000); //<50 no work, 60-100 slow, 400-1000 quick, 2000 very quick

LeonStepper.setCurrent(0.8);//0.8 or 1
LeonStepper.setStepsPerUnit(1);//4 for CoreXY, 1-7 slower, 8 fast, >9 no work
LeonStepper.setAccel(1000); //<50 no work, 60-100 slow, 400-1000 quick, 2000 very quick

const machine = createSynchronizer([yuichiStepper, LeonStepper]);

machine.setPosition([0, 0]);
console.log("pos1 "+await machine.getPosition());

async function slideY(valueY){
    console.log(valueY);
    await machine.absolute([valueY, valueY]);
console.log("pos"+await machine.getPosition());
}

async function slideX(valueX){
    console.log(valueX);
    await machine.absolute([valueX, -valueX]);
console.log("pos"+await machine.getPosition());
}

console.log("pos3 "+await machine.getPosition());

async function move(){
  let pos = 1;
    await yuichiStepper.absolute(pos);
    await LeonStepper.absolute(pos);
}
//}




const el = document.createElement("div");

el.style = `
  padding: 10px;
`

el.innerHTML = `
  <button>press this</button>
  <div>Y-Axis Slider</div>
  <input type="range" min="1" max="100" value="50" id="rangeSliderY">
  <p>Value: <span id="rangeValueY"></span></p>

  <div>X-Axis Slider</div>
  <input type="range" min="1" max="100" value="50" id="rangeSliderX">
  <p>Value: <span id="rangeValueX"></span></p>

  <style>
  td {text-align: center;}
  </style>
 <table>
  <tr>
    <td><button id="XY1"> XY1</button></td>
    <td><button id="Y+">Y+</button></td>
    <td><button id="XY2"> XY2</button></td>
  </tr>
  <tr>
    <td><button id="X-">X-</button></td>
    <td><button>Home</button></td>
    <td><button id="X+">X+</button></td>
  </tr>
  <tr>
    <td><button id="XY3"> XY3</button></td>
    <td><button id="Y-">Y-</button></td>
    <td><button id="XY4"> XY4</button></td>
  </tr>
</table>

`;

const rangeSliderY = el.querySelector("#rangeSliderY");
const rangeValueY = el.querySelector("#rangeValueY");

rangeSliderY.addEventListener("input", (event) => {
  const valueY = event.target.value;
  rangeValueY.textContent = valueY;
  slideY(valueY); 
});

const rangeSliderX = el.querySelector("#rangeSliderX");
const rangeValueX = el.querySelector("#rangeValueX");

rangeSliderX.addEventListener("input", (event) => {
  const valueX = event.target.value;
  rangeValueX.textContent = valueX;
  slideX(valueX);
});

el
  .querySelector("button")
  .querySelector("#X+");
  .addEventListener("click", () => {
    move()
})




render(el);

Press Buttons to move

yuichiStepper.setCurrent(0.8);//0.8 or 1
yuichiStepper.setStepsPerUnit(5);//4 for CoreXY, 1-7 slower, 8 fast, >9 no work
yuichiStepper.setAccel(1000); //<50 no work, 60-100 slow, 400-1000 quick, 2000 very quick

LeonStepper.setCurrent(0.8);//0.8 or 1
LeonStepper.setStepsPerUnit(5);//4 for CoreXY, 1-7 slower, 8 fast, >9 no work
LeonStepper.setAccel(1000); //<50 no work, 60-100 slow, 400-1000 quick, 2000 very quick

const machine = createSynchronizer([yuichiStepper, LeonStepper]);

const el = document.createElement("div");
var Yval = 0;
var Xval = 0;


async function moveYplus(Yval){
    console.log(Yval);
    await machine.absolute([Yval, Yval]);
}
async function moveYminus(Yval){
    console.log(Yval);
    await machine.absolute([Yval, Yval]);
}
async function moveXplus(Xval){
    console.log(Xval);
    await machine.absolute([Xval, Xval]);
}
async function moveXminus(Xval){
    console.log(Xval);
    await machine.absolute([Yval, Xval]);
}


async function moveToZero(Yval){
    console.log(Yval);
    await machine.absolute([-Yval, -Yval]);
}


el.style = `
  padding: 10px;
`

el.innerHTML = `

  <style>
  td {text-align: center;}
  </style>
 <table>
  <tr>
    <td><button id="XY1"> XY1</button></td>
    <td><button id="Yplus">Y+</button></td>
    <td><button id="XY2"> XY2</button></td>
  </tr>
  <tr>
    <td><button id="Xminus">X-</button></td>
    <td><button id="Zero">Home</button></td>
    <td><button id="Xplus">X+</button></td>
  </tr>
  <tr>
    <td><button id="XY3"> XY3</button></td>
    <td><button id="Yminus">Y-</button></td>
    <td><button id="XY4"> XY4</button></td>
  </tr>
</table>
`;

el
  .querySelector("#Yplus")
  .addEventListener("click", () => {
    Yval = Yval+1;
    console.log(Yval);
    moveYplus(Yval);
  })

el
  .querySelector("#Yminus")
  .addEventListener("click", () => {
    Yval = Yval-1;
    console.log(Yval);
    moveYminus(Yval);
  })

el
  .querySelector("#Xminus")
  .addEventListener("click", () => {
    Xval = Xval-1;
    console.log(Xval);
    moveXminus(Xval);
  })

el
  .querySelector("#Xplus")
  .addEventListener("click", () => {
    Xval = Xval+5;
    console.log(Xval);
    moveXplus(Xval);
  })

el
  .querySelector("#Zero")
  .addEventListener("click", () => {
    console.log(Yval);
    moveToZero(-Yval);
    Yval = 0;
    Xval =0;
  })

render(el);
//Ver 9Jan end
motorA.setCurrent(0.8);//0.8 or 1
motorA.setStepsPerUnit(5);//4 for CoreXY, 1-7 slower, 8 fast, >9 no work
motorA.setAccel(1000); //<50 no work, 60-100 slow, 400-1000 quick, 2000 very quick

motorB.setCurrent(0.8);//0.8 or 1
motorB.setStepsPerUnit(5);//4 for CoreXY, 1-7 slower, 8 fast, >9 no work
motorB.setAccel(1000); //<50 no work, 60-100 slow, 400-1000 quick, 2000 very quick


const machine = createSynchronizer([motorA, motorB]);

const el = document.createElement("div");
var Yval = 0;
var Xval = 0;


async function moveYplus(Yval){
    console.log(Yval);
    await machine.absolute([Yval, Yval]);
}
async function moveYminus(Yval){
    console.log(Yval);
    await machine.absolute([Yval, Yval]);
}
async function moveXplus(Xval){
    console.log(Xval);
    await machine.absolute([Xval, Xval]);
}
async function moveXminus(Xval){
    console.log(Xval);
    await machine.absolute([Yval, Xval]);
}


async function moveToZero(Yval){
    console.log(Yval);
    await machine.absolute([-Yval, -Yval]);
}


el.style = `
  padding: 10px;
`

el.innerHTML = `

 <style>td {text-align: center;}</style>
 <table>
  <tr>
    <td><button id="XY1"> XY1</button></td>
    <td><button id="Yplus">Y+</button></td>
    <td><button id="XY2"> XY2</button></td>
  </tr>
  <tr>
    <td><button id="Xminus">X-</button></td>
    <td><button id="Zero">Home</button></td>
    <td><button id="Xplus">X+</button></td>
  </tr>
  <tr>
    <td><button id="XY3"> XY3</button></td>
    <td><button id="Yminus">Y-</button></td>
    <td><button id="XY4"> XY4</button></td>
  </tr>
</table>
`;

el
  .querySelector("#Yplus")
  .addEventListener("click", () => {
    Yval = Yval+1;
    console.log(Yval);
    moveYplus(Yval);
  })

el
  .querySelector("#Yminus")
  .addEventListener("click", () => {
    Yval = Yval-1;
    console.log(Yval);
    moveYminus(Yval);
  })

el
  .querySelector("#Xminus")
  .addEventListener("click", () => {
    Xval = Xval-1;
    console.log(Xval);
    moveXminus(Xval);
  })

el
  .querySelector("#Xplus")
  .addEventListener("click", () => {
    Xval = Xval+5;
    console.log(Xval);
    moveXplus(Xval);
  })

el
  .querySelector("#Zero")
  .addEventListener("click", () => {
    console.log(Yval);
    moveToZero(-Yval);
    Yval = 0;
    Xval =0;
  })

render(el);

Note

#define PIN_LIMIT 29//26

Code from Leo

//motorRight is motorB
await motorB.setCurrent(1);
await motorB.setStepsPerUnit(5);// conversion to linear distance

//motorLeft is motorA
await motorA.setCurrent(1);
await motorA.setStepsPerUnit(5);

const machine = createSynchronizer([motorB, motorA]);//([motorRight],[motorLeft])

async function goTo(x,y){
  await machine.absolute([x-y],[x+y]);
}

await machine.setPosition([0,0]);

const machineXlen = 400;//where to relate in this code?
const machineYlen = 471;

var pts = [[2,2,0],[-2,-2,0]];//path

async function runAlongPath(){

  //run
  for (let i = 0; i < pts.length; i++){
    await goTo(pts[i][0], pts[i][1]);
    //await pump.pulseGate(1,15)//if have a pump
    }

  await goTo(0,0);
}

await runAlongPath();

my test code about pts

//await motorB.setCurrent(1);
//await motorB.setStepsPerUnit(5);

//await motorA.setCurrent(1);
//await motorA.setStepsPerUnit(5);

//const machine = createSynchronizer([motorB, motorA]);

//await machine.setPosition([0,0]);

async function goTo(x,y){
  //await machine.absolute([x-y],[x+y]);
}



//const machineXlen = 10;
//const machineYlen = 10;

var pts = [[2,2],[2,-2],[-2,-2],[2,2]];
console.log("pts.length= "+pts.length);

async function runAlongPath(){

  //run
  for (let i=0; i<pts.length; i++){
    await goTo(pts[i][0], pts[i][1]);
    console.log("i= "+ i);
    console.log("goTo("+pts[i][0]+","+pts[i][1]+")");
    //await pump.pulseGate(1,15)
    }
  //await goTo(0,0);
}

await runAlongPath();

Controlled!!

// warning: without a powered usb-hub, currentScale > 0.5 are likely to fail 
await motorA.setCurrent(1);
await motorA.setStepsPerUnit(5);

await motorB.setCurrent(1);
await motorB.setStepsPerUnit(5);

const machine = createSynchronizer([motorA, motorB]);

machine.setPosition([0, 0]);

//left 10,10
//right -10, -10
//up 10,-10
//down -10,10

async function goTo(x,y){
 //await machine.absolute([x,y]);
await machine.absolute([x-y,x+y]);
//await machine.absolute([0, 0]);

}


for (let i = 0; i < 3; i++) {
  //await machine.absolute([-10, -10]);
  await goTo(5,0);
  await delay(100);
  await goTo(5,5);
  await delay(100);
  await goTo(0,5);
  await delay(100);
  await goTo(0,0);
}

// warning: without a powered usb-hub, currentScale > 0.5 are likely to fail 
await motorA.setCurrent(1);
await motorA.setStepsPerUnit(5);

await motorB.setCurrent(1);
await motorB.setStepsPerUnit(5);

const machine = createSynchronizer([motorA, motorB]);

machine.setPosition([0, 0]);

//left 10,10
//right -10, -10
//up 10,-10
//down -10,10



console.log(motorA.getLimitState());


async function goToZeroX(){
  while(motorA.getLimitState()){
    for (let i = 0; i < 10; i++) {
      await goTo(-i,0);
  }
}

goToZeroX();

async function goTo(x,y){
 //await machine.absolute([x,y]);
await machine.absolute([-x-y,-x+y]);
//await machine.absolute([0, 0]);

}


for (let i = 0; i < 1; i++) {
  //await machine.absolute([-10, -10]);
  await goTo(5,0);//move to right
  await delay(100);
  await goTo(5,5);//
  await delay(100);
  await goTo(0,5);//
  await delay(100);
  await goTo(0,0);//
}

Homing to hit limit switches

// warning: without a powered usb-hub, currentScale > 0.5 are likely to fail 
await motorA.setCurrent(1);
await motorA.setStepsPerUnit(5);

await motorB.setCurrent(1);
await motorB.setStepsPerUnit(5);

const machine = createSynchronizer([motorA, motorB]);

machine.setPosition([0, 0]);

//left 10,10
//right -10, -10
//up 10,-10
//down -10,10
const isAtEndStopX = false;

console.log(isAtEndStopX);



async function goToZeroX2(){
  while(await motorA.getLimitState()){
    motorA.velocity(10);
    motorB.velocity(10);  
  }
  //motorA.velocity(0);
  //motorB.velocity(0);
  while(await motorB.getLimitState()){
    motorA.velocity(10);
    motorB.velocity(-10);  
  }
  motorA.velocity(0);
  motorB.velocity(0);
  machine.setPosition([0, 0]);
  await delay(1000);

  goTo(1,1);
}


async function goToZeroX() {
  while (!isAtEndStopX) {
    for (let i = 0; i < 100; i++) {
      await goTo(-i, 0);
      // Check endstop condition here or update isAtEndStopX based on some condition
      if (await motorA.getLimitState() == false) {
        isAtEndStopX = true;
        break; // Exit the loop if the endstop is reached
      }
    }
  }
}
goToZeroX2();

async function goTo(x,y){
 //await machine.absolute([x,y]);
  console.log(`Moving to (${x}, ${y})`);
  await machine.absolute([-x-y,-x+y]);
//await machine.absolute([0, 0]);
}


//for (let i = 0; i < 1; i++) {
 // //await machine.absolute([-10, -10]);
 // await goTo(5,0);//move to right
 // await delay(100);
 // await goTo(5,5);//
 // await delay(100);
 // await goTo(0,5);//
 // await delay(100);
 // await goTo(0,0);//
//}

Home and Draw square

// warning: without a powered usb-hub, currentScale > 0.5 are likely to fail 
await motorA.setCurrent(1);
await motorA.setStepsPerUnit(5);

await motorB.setCurrent(1);
await motorB.setStepsPerUnit(5);

const machine = createSynchronizer([motorA, motorB]);

machine.setPosition([0, 0]);

//const isAtEndStopX = false;

//console.log(isAtEndStopX);



async function goToHome(){
  while(await motorA.getLimitState()){
    motorA.velocity(10);
    motorB.velocity(10);  
  }
  while(await motorB.getLimitState()){
    motorA.velocity(10);
    motorB.velocity(-10);  
  }
  motorA.velocity(0);
  motorB.velocity(0);
  machine.setPosition([0, 0]);
  await delay(1000);
  goTo(1,1);
  machine.setPosition([0, 0]);
  await delay(1000);
}

//goToHome();

async function goTo(x,y){
  console.log(`Moving to (${x}, ${y})`);
  await machine.absolute([-x-y,-x+y]);
}

async function drawSquare(){
  await goTo(5,0);//move to right
  await goTo(5,5);//move up
  await goTo(0,5);//move left
  await goTo(0,0); //move down
}

drawSquare();

//left 10,10
//right -10, -10
//up 10,-10
//down -10,10
//for (let i = 0; i < 1; i++) {
  //await machine.absolute([-10, -10]);
  //await goTo(5,0);//move to right
  //await delay(100);
  //await goTo(5,5);//
  //await delay(100);
  //await goTo(0,5);//
  //await delay(100);
  //await goTo(0,0);//
//}

Home and Draw from position array

// warning: without a powered usb-hub, currentScale > 0.5 are likely to fail 
await motorA.setCurrent(1);
await motorA.setStepsPerUnit(5);

await motorB.setCurrent(1);
await motorB.setStepsPerUnit(5);

const machine = createSynchronizer([motorA, motorB]);

machine.setPosition([0, 0]);

//const isAtEndStopX = false;

//console.log(isAtEndStopX);



async function goToHome(){
  while(await motorA.getLimitState()){
    motorA.velocity(10);
    motorB.velocity(10);  
  }
  while(await motorB.getLimitState()){
    motorA.velocity(10);
    motorB.velocity(-10);  
  }
  motorA.velocity(0);
  motorB.velocity(0);
  machine.setPosition([0, 0]);
  await delay(1000);
  goTo(1,1);
  machine.setPosition([0, 0]);
  await delay(1000);
}

//goToHome();

async function goTo(x,y){
  console.log(`Moving to (${x}, ${y})`);
  await machine.absolute([-x-y,-x+y]);
}

async function drawSquare(){
  await goTo(5,0);//move to right
  await goTo(5,5);//move up
  await goTo(0,5);//move left
  await goTo(0,0); //move down
}

//drawSquare();


var pts = [[5,0],[5,5],[0,5],[0,0]];
console.log("pts.length= "+pts.length);

async function runAlongPath(){
  for (let i = 0; i < pts.length; i++){
    await goTo(pts[i][0], pts[i][1]);
    await delay(1000);  
  }
}

runAlongPath();

//left 10,10
//right -10, -10
//up 10,-10
//down -10,10
//for (let i = 0; i < 1; i++) {
  //await machine.absolute([-10, -10]);
  //await goTo(5,0);//move to right
  //await delay(100);
  //await goTo(5,5);//
  //await delay(100);
  //await goTo(0,5);//
  //await delay(100);
  //await goTo(0,0);//
//}

DrawStar from button

// warning: without a powered usb-hub, currentScale > 0.5 are likely to fail 

const el = document.createElement("div");

el.style = `
  padding: 10px;
`

el.innerHTML = `
<button id="Home"> Home</button>
<p>
<button id="Draw"> Draw</button>
<p>
<button id="DrawStar"> DrawStar</button>
`;

el
  .querySelector("#Home")
  .addEventListener("click", () => {
    goToHome();
  })

el
  .querySelector("#Draw")
  .addEventListener("click", () => {
    delay(100);
    draw();
  })

el
  .querySelector("#DrawStar")
  .addEventListener("click", () => {
    delay(100);
    drawStar();
  })

render(el);

motorA.setCurrent(1);
motorA.setStepsPerUnit(5);

motorB.setCurrent(1);
motorB.setStepsPerUnit(5);

const machine = createSynchronizer([motorA, motorB]);

machine.setPosition([0, 0]);

//const isAtEndStopX = false;

//console.log(isAtEndStopX);



async function goToHome(){
  while(await motorA.getLimitState()){
    motorA.velocity(10);
    motorB.velocity(10);  
  }
  while(await motorB.getLimitState()){
    motorA.velocity(10);
    motorB.velocity(-10);  
  }
  motorA.velocity(0);
  motorB.velocity(0);
  machine.setPosition([0, 0]);
  await delay(1000);
  goTo(2,2);
  machine.setPosition([0, 0]);
  await delay(1000);
}

//goToHome();
async function goTo(x,y){
  console.log(`Moving to (${x}, ${y})`);
  await machine.absolute([-x-y,-x+y]);
}


//Square
var pts = [[50,0],[50,50],[0,50],[0,0]];

//Star
var ptsStar = [[20,10],[30,50],[40,10],[10,40],[50,40],[20,10]];


async function draw(){
  for (let i = 0; i < pts.length; i++){
    await goTo(pts[i][0], pts[i][1]);
    await delay(200);  
  }
}

async function drawStar(){
  for (let i = 0; i < ptsStar.length; i++){
    await goTo(ptsStar[i][0], ptsStar[i][1]);
    await delay(200);  
  }
}

for bootcamp repo

// warning: without a powered usb-hub, currentScale > 0.5 are likely to fail 

const el = document.createElement("div");

el.style = `
  padding: 10px;
`

el.innerHTML = `
<button id="Home"> Home</button>
<p>
<button id="Draw"> DrawSquare</button>
<p>
<button id="DrawStar"> DrawStar</button>
`;

el
  .querySelector("#Home")
  .addEventListener("click", () => {
    goToHome();
  })

el
  .querySelector("#Draw")
  .addEventListener("click", () => {
    delay(100);
    draw();
  })

el
  .querySelector("#DrawStar")
  .addEventListener("click", () => {
    delay(100);
    drawStar();
  })

render(el);

motorA.setCurrent(1);
motorA.setStepsPerUnit(5);

motorB.setCurrent(1);
motorB.setStepsPerUnit(5);

const machine = createSynchronizer([motorA, motorB]);

machine.setPosition([0, 0]);

//const isAtEndStopX = false;

//console.log(isAtEndStopX);



async function goToHome(){
  while(await motorA.getLimitState()){
    motorA.velocity(10);
    motorB.velocity(10);  
  }
  while(await motorB.getLimitState()){
    motorA.velocity(10);
    motorB.velocity(-10);  
  }
  motorA.velocity(0);
  motorB.velocity(0);
  machine.setPosition([0, 0]);
  await delay(1000);
  goTo(2,2);
  machine.setPosition([0, 0]);
  await delay(1000);
}

//goToHome();
async function goTo(x,y){
  console.log(`Moving to (${x}, ${y})`);
  await machine.absolute([-x-y,-x+y]);
}


//Square
var pts = [[50,0],[50,50],[0,50],[0,0]];

//Star
var ptsStar = [[20,10],[30,50],[40,10],[10,40],[50,40],[20,10]];


async function draw(){
  for (let i = 0; i < pts.length; i++){
    await goTo(pts[i][0], pts[i][1]);
    await delay(200);  
  }
}

async function drawStar(){
  for (let i = 0; i < ptsStar.length; i++){
    await goTo(ptsStar[i][0], ptsStar[i][1]);
    await delay(200);  
  }
}


Last update: January 11, 2024