Skip to content

Modular things

Ref. modular-things

Install

(1) install [node.js](https://nodejs.org/en/) - please use version 16.15.1 or above

(2) clone this repo

(3) navigate to <this-repo>/js and do npm install in the terminal

(1) Install node.js

% echo $PATH
/usr/local/bin

% node --version
v19.8.1
% npm --version
9.5.1

(2) clone this repo

% cd repos
% git clone https://github.com/modular-things/modular-things.git
Cloning into 'modular-things'...
...
Resolving deltas: 100% (1324/1324), done.
% ls
modular-things
% cd modular-things
% ls
LICENSE.md      astro.config.mjs    public
README.md       examples        src
TODO.md         log         tsconfig.json
arduino         package.json        yarn.lock

(3) navigate to this-repo/js and do npm install in the terminal

There is no this-repo/js folder in this repo. (see tree below)
But there is this-repo/package.json

Notes

引数のない npm install コマンド実行をすると、カレントディレクトリにある package.json に記述されている情報を元に、そこに記述されている パッケージを node_modules (インストール先)にインストールします。

If you run the npm install command without arguments, based on the information described in package.json in the current directory, the package described there will be installed to node_modules (installation destination).

% pwd
/Users/yuichi/repos/modular-things
% tree
.
├── LICENSE.md
├── README.md
├── TODO.md
├── arduino
│   ├── accelerometer-thing
│   │   └── accelerometer-thing.ino
│   ├── capacitive-thing
│   │   └── capacitive-thing.ino
│   ├── dc-encoder-thing
│   │   └── dc-encoder-thing.ino
│   ├── mosfet-thing
│   │   └── mosfet-thing.ino
│   ├── oled-thing
│   │   └── oled-thing.ino
│   ├── potentiometer-thing
│   │   └── potentiometer-thing.ino
│   ├── rgbb-thing
│   │   └── rgbb-thing.ino
│   ├── rgbb-thing-rpc
│   │   └── rgbb-thing-rpc.ino
│   ├── rpc-mule
│   │   └── rpc-mule.ino
│   ├── servo-thing
│   │   └── servo-thing.ino
│   ├── stepper-hbridge
│   │   ├── motionStateMachine.cpp
│   │   ├── motionStateMachine.h
│   │   ├── stepper-hbridge.ino
│   │   ├── stepperDriver.cpp
│   │   └── stepperDriver.h
│   ├── stepper-hbridge-rp2040
│   │   ├── motionStateMachine.cpp
│   │   ├── motionStateMachine.h
│   │   ├── stepper-hbridge-rp2040.ino
│   │   ├── stepperDriver.cpp
│   │   └── stepperDriver.h
│   └── time-of-flight
│       └── time-of-flight.ino
├── astro.config.mjs
├── examples
│   ├── examples
│   │   ├── circleMachine.js
│   │   ├── corexy_machine.js
│   │   ├── potentiometerMachine.js
│   │   ├── sequencer.js
│   │   ├── songs
│   │   │   └── avril.txt
│   │   ├── viewWindow.js
│   │   ├── websocket_example
│   │   │   ├── client.js
│   │   │   └── server.py
│   │   ├── xylophone.js
│   │   └── xylophone_sequencer.js
│   ├── machine-interface.js
│   └── web-serial-test.html
├── log
│   ├── 2022-10_jakes-modular-thing-log.md
│   ├── 2022-11_jakes-modular-thing-motion-notes.md
│   ├── 2022-11_usb-motion-perf-tests-log.md
│   ├── 2022-12_jakes-fixed-point-log.md
│   ├── 2022-12_modular-things-oshwa-prop.md
│   ├── 2022-12_xylophone-log.md
│   ├── images
│   │   └── 2022-12-15_fixed-points-01.png
│   └── video
│       ├── mt-01-intro.mp4
│       ├── mt-02-ui.mp4
│       ├── mt-03-xylophone.mp4
│       └── mt-04-machineweek.mp4
├── package.json
├── public
│   └── machine-interface.js
├── src
│   ├── components
│   │   ├── HelpMarkdown.md
│   │   ├── ScanButton.jsx
│   │   ├── SideMenu.tsx
│   │   ├── TopMenu.jsx
│   │   ├── codemirror.tsx
│   │   └── index.jsx
│   ├── env.d.ts
│   ├── lib
│   │   ├── SAMPLES.js
│   │   ├── bundle-eval
│   │   │   ├── fs.ts
│   │   │   └── run.ts
│   │   ├── codemirror
│   │   │   └── init.ts
│   │   ├── download.js
│   │   ├── events
│   │   │   ├── addDividerDrag.js
│   │   │   └── listen.js
│   │   ├── global_state.ts
│   │   ├── init.js
│   │   ├── modularThingClient.ts
│   │   ├── osapjs
│   │   │   ├── LICENSE.md
│   │   │   ├── README.md
│   │   │   ├── core
│   │   │   │   ├── endpoint.js
│   │   │   │   ├── highLevel.js
│   │   │   │   ├── loop.js
│   │   │   │   ├── mvc.js
│   │   │   │   ├── netRunner.js
│   │   │   │   ├── osap.js
│   │   │   │   ├── packets.js
│   │   │   │   ├── query.js
│   │   │   │   ├── queryMSeg.js
│   │   │   │   ├── rpc.js
│   │   │   │   ├── time.js
│   │   │   │   ├── ts.js
│   │   │   │   ├── vertex.js
│   │   │   │   └── vport.js
│   │   │   ├── utes
│   │   │   │   ├── cobs.js
│   │   │   │   └── diff.js
│   │   │   └── vport
│   │   │       ├── vPortSerial.js
│   │   │       └── vPortWebSerial.ts
│   │   ├── runCode.js
│   │   ├── setThingsState.js
│   │   └── virtualThings
│   │       ├── TODO_breadboard.js
│   │       ├── accelerometer.js
│   │       ├── capacitive.js
│   │       ├── mosfet.js
│   │       ├── oled.js
│   │       ├── potentiometer.js
│   │       ├── rgbb.js
│   │       ├── servo.js
│   │       ├── stepper.js
│   │       ├── synchronizer.js
│   │       └── timeOfFlight.js
│   ├── pages
│   │   └── index.astro
│   └── styles
│       ├── HelpMarkdown.module.css
│       ├── SideMenu.module.css
│       ├── TopMenu.module.css
│       ├── codemirror.module.css
│       └── global.css
├── tsconfig.json
└── yarn.lock
% pwd                     
/Users/yuichi/repos/modular-things
% npm install

added 434 packages, and audited 435 packages in 48s

164 packages are looking for funding
  run `npm fund` for details

5 high severity vulnerabilities

To address all issues, run:
  npm audit fix

Run `npm audit` for details.
npm notice
npm notice New minor version of npm available! 9.5.1 -> 9.6.2
npm notice Changelog: https://github.com/npm/cli/releases/tag/v9.6.2
npm notice Run npm install -g npm@9.6.2 to update!
npm notice

Run

Run
(1) from <this-repo>/js do npm run start

(2) navigate (in the browser) to http://localhost:8080/client/

(1) do npm run start

% pwd                     
/Users/yuichi/repos/modular-things
% npm run start

> sprig-3@1.0.0 start
> astro dev

  🚀  astro  v2.0.4 started in 25ms

  ┃ Local    http://localhost:3000/modular-things/
  ┃ Network  use --host to expose

The following dependencies are imported but could not be resolved:

  serialport (imported by /Users/yuichi/repos/modular-things/src/lib/osapjs/vport/vPortSerial.js)

Are they installed?
16:48:53 [serve]    404                             /favicon.ico

(2) navigate (in the browser) to http://localhost:8080/client/

Writing New modular-things

For embedded (arduino) codes, install the OSAP library, which you can download as a zip here: https://github.com/jakeread/osap-arduino, and should also be available via arduino's library manager.

Also, install the FlashStorage_SAMD library, via the library manager.

We use the ArduinoCore-fab-sam for these circuits, which you can install into Arduino via the notes in that repo.

Install the OSAP library

Download zip from here

Install the FlashStorage_SAMD library, via the library manager.

Board core

Install from here

https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json

Install from here

https://raw.githubusercontent.com/qbolsee/ArduinoCore-fab-sam/master/json/package_Fab_SAM_index.json

Board

Ref. modular-things-circuits

there circuits

code

% pwd
/Users/yuichi/repos/modular-things/arduino
% tree
.
├── accelerometer-thing
│   └── accelerometer-thing.ino
├── capacitive-thing
│   └── capacitive-thing.ino
├── dc-encoder-thing
│   └── dc-encoder-thing.ino
├── mosfet-thing
│   └── mosfet-thing.ino
├── oled-thing
│   └── oled-thing.ino
├── potentiometer-thing
│   └── potentiometer-thing.ino
├── rgbb-thing
│   └── rgbb-thing.ino
├── rgbb-thing-rpc
│   └── rgbb-thing-rpc.ino
├── rpc-mule
│   └── rpc-mule.ino
├── servo-thing
│   └── servo-thing.ino
├── stepper-hbridge
│   ├── motionStateMachine.cpp
│   ├── motionStateMachine.h
│   ├── stepper-hbridge.ino
│   ├── stepperDriver.cpp
│   └── stepperDriver.h
├── stepper-hbridge-rp2040
│   ├── motionStateMachine.cpp
│   ├── motionStateMachine.h
│   ├── stepper-hbridge-rp2040.ino
│   ├── stepperDriver.cpp
│   └── stepperDriver.h
└── time-of-flight
    └── time-of-flight.ino

Xiao RP2040

Board

stepper-hbridge
brd sch
top outline
Download Eagle BRD SCH(wip)
stepper-hbridge
brd sch

code

Notes

https://github.com/earlephilhower/arduino-pico

├── stepper-hbridge-rp2040
│   ├── motionStateMachine.cpp
│   ├── motionStateMachine.h
│   ├── stepper-hbridge-rp2040.ino
│   ├── stepperDriver.cpp
│   └── stepperDriver.h
download from this repo

#include "motionStateMachine.h"
#include "stepperDriver.h"
#include <osap.h>
#include <vt_endpoint.h>
#include <vp_arduinoSerial.h>
#include <core/ts.h>

// ---------------------------------------------- OSAP central-nugget
// message-passing memory allocation
#define OSAP_STACK_SIZE 12
VPacket messageStack[OSAP_STACK_SIZE];
OSAP osap("stepper", messageStack, OSAP_STACK_SIZE);

// ---------------------------------------------- 0th Vertex: OSAP USB Serial
VPort_ArduinoSerial vp_arduinoSerial(&osap, "usbSerial", &Serial);

// ---------------------------------------------- 1th Vertex: Target Requests (pos, or velocity)
EP_ONDATA_RESPONSES onTargetData(uint8_t* data, uint16_t len){
  uint16_t wptr = 0;
  // there's no value in getting clever here: we have two possible requests...
  if(data[wptr ++] == MOTION_MODE_POS){
    float targ = ts_readFloat32(data, &wptr);
    float maxVel = ts_readFloat32(data, &wptr);
    float maxAccel = ts_readFloat32(data, &wptr);
    motion_setPositionTarget(targ, maxVel, maxAccel);
  } else if (data[wptr ++] == MOTION_MODE_VEL){
    float targ = ts_readFloat32(data, &wptr);
    float maxAccel = ts_readFloat32(data, &wptr);
    motion_setVelocityTarget(targ, maxAccel);
  }
  return EP_ONDATA_ACCEPT;
}

Endpoint targetEndpoint(&osap, "targetState", onTargetData);

// ---------------------------------------------- 2nd Vertex: Motion State Read
// queries only, more or less, so
EP_ONDATA_RESPONSES onMotionStateData(uint8_t* data, uint16_t len){ return EP_ONDATA_REJECT; }

boolean beforeMotionStateQuery(void);

Endpoint stateEndpoint(&osap, "motionState", onMotionStateData, beforeMotionStateQuery);

uint8_t stateData[12];

boolean beforeMotionStateQuery(void){
  motionState_t state;
  motion_getCurrentStates(&state);
  uint16_t rptr = 0;
  ts_writeFloat32(state.pos, stateData, &rptr);
  ts_writeFloat32(state.vel, stateData, &rptr);
  ts_writeFloat32(state.accel, stateData, &rptr);
  stateEndpoint.write(stateData, 12);
  // in-fill current posn, velocity, and acceleration
  return true;
}

// ---------------------------------------------- 3rd Vertex: Set Current Position
EP_ONDATA_RESPONSES onPositionSetData(uint8_t* data, uint16_t len){
  // should do maxAccel, maxVel, and (optionally) setPosition
  // upstream should've though of this, so,
  uint16_t rptr = 0;
  float pos = ts_readFloat32(data, &rptr);
  motion_setPosition(pos);
  return EP_ONDATA_ACCEPT;
}

Endpoint positionSetEndpoint(&osap, "setPosition", onPositionSetData);

// ---------------------------------------------- 4th Vertex: Settings catch-all,

EP_ONDATA_RESPONSES onSettingsData(uint8_t* data, uint16_t len){
  // it's just <cscale> for the time being,
  uint16_t rptr = 0;
  float cscale = ts_readFloat32(data, &rptr);
  stepper_setCScale(cscale);
  return EP_ONDATA_ACCEPT;
}

Endpoint settingsEndpoint(&osap, "settings", onSettingsData);

// ---------------------------------------------- 5th Vertex: Limit / Switch Output... non-op at the moment,

// fair warning, this is unused at the moment... and not set-up,
// also the limit pin is config'd to look at the interrupt on a scope at the moment, see motionStateMachine.cpp
Endpoint buttonEndpoint(&osap, "buttonState");

void setup() {
  Serial.begin(0);
  // ~ important: the stepper code initializes GCLK4, which we use as timer-interrupt
  // in the motion system, so it aught to be initialized first !
  stepper_init();
  // another note on the motion system:
  // at the moment, we have a relatively small absolute-maximum speed: say the integrator interval is 250us,
  // we have 0.00025 seconds between ticks, for a max of 4000 steps / second...
  // we are then microstepping at 1/4th steps, for 800 steps per motor revolution, (from a base of 200)
  // meaning we can make only 5 revs / sec, or 300 rippums (RPM),
  // with i.e. a 20-tooth GT2 belt, we have 40mm of travel per revolution, making only 200mm/sec maximum traverse
  // this is not pitiful, but not too rad, and more importantly is that we will want to communicate these limits
  // to users of the motor - so we should outfit a sort of settings-grab function, or something ?
  motion_init(250);
  // uuuh...
  osap.init();
  // run the commos
  vp_arduinoSerial.begin();
  pinMode(PIN_BUT, INPUT_PULLUP);
}

uint32_t debounceDelay = 1;
uint32_t lastButtonCheck = 0;
boolean lastButtonState = false;

void loop() {
  // do graph stuff
  osap.loop();
  // if(lastIntegration + integratorInterval < micros()){
  //   // stepper_step(1, true);
  //   lastIntegration = micros();
  //   motion_integrate();
  // }
  // debounce and set button states,
  if(lastButtonCheck + debounceDelay < millis()){
    lastButtonCheck = millis();
    boolean newState = digitalRead(PIN_BUT);
    if(newState != lastButtonState){
      lastButtonState = newState;
      // invert on write: vcc-low is button-down, but we should be "true" when down and "false" when up
      buttonEndpoint.write(!lastButtonState);
    }
  }
}

Last update: September 27, 2023