# SCF4 # About ### General Description Tiny self-sufficient stepper motor controller **SCF4-M** module is designed for high integration customer products and can drive FIZ+ lens with 3 stepper motors (for example Focus/Zoom/P-Iris with micro-stepping up to 1/1024 steps for inaudible operation) and IR filter simultaneously. Also has 3 limit switch inputs and 4 GPIO (IN/OUT/ADC) pins for custom application control. The controller expects industry-standard G-code formatted commands for fastest and easiest integration. Designed to be connected over single USB cable (USART and I2C can be supported in custom firmware). Firmware modifications can be tailored to suit customer requirements. SCF4 - is a one in a series of Kurokesu stepper motor controllers and stands for Stepper Controller Model F, 4'th modification. ### Features - Small footprint 16 x 23 x 2.3 mm \[0.63 x 0.91 x 0.09 in\] - 3x stepper motor controller with up to 1/1024 micro-stepping support for each motor - 1x H-bridge for coil control (day/night filter switch) - 3x limit switch processing for precise lens homing/referencing - Direct USB Full-speed (12 Mbit/s) connectivity - 4x GPIO's with Input/Output/Analog functionality - Industry standard G-code command set - Can drive most lenses with bipolar stepper motors with minor or none tuning - Certificates: REACH, RoHS, CE ### Applications - Motorized zoom lenses - Small test fixtures - Micro mechanism control# SCF4-M module ## Pin description [![SCF4-M_motor_diagram.png](https://wiki.kurokesu.com/uploads/images/gallery/2021-01/scaled-1680-/SCF4-M_motor_diagram.png)](https://wiki.kurokesu.com/uploads/images/gallery/2021-01/SCF4-M_motor_diagram.png) ## Technical specifications
Module dimensions16 x 23 x 2.3 mm \[0.63 x 0.91 x 0.09 in\]
Controlled stepper motors3
Connectivity**USB** (optional USART, I2C, SPI)
Module pin count29
Stepper motor resolutionup to 1/1024 micro-steps (1/64 default)
PWM voltage levels for filter switchH-Bridge (128 voltage levels)
Weight0.9g
Power consumption (module only)55mA @ 5V
Power consumption (operating x18 lens 2 motors)180mA @ 5V
## Absolute maximum ratings
Min supply voltage4.3V
Max supply voltage7.0 V
Stepper motor max current200mA @ 5V
IR Filter coil max current300mA @ 5V
## Operating parameters
Operating voltage4.5 ~ 5.5V
Controller max current consumption1A @ 5V
Controller power rating5W
Relative HumidityNon-Condensing
Operating Temperature-40 ~ 85°C
## Mechanical dimensions [![SCF4M_dimensions.png](https://wiki.kurokesu.com/uploads/images/gallery/2021-01/scaled-1680-/SCF4M_dimensions.png)](https://wiki.kurokesu.com/uploads/images/gallery/2021-01/SCF4M_dimensions.png) ## Test points For testing, flashing firmware and post-production purposes SCF4-M module has several test points. [![SCF4-M-tps.png](https://wiki.kurokesu.com/uploads/images/gallery/2021-01/scaled-1680-/SCF4-M-tps.png)](https://wiki.kurokesu.com/uploads/images/gallery/2021-01/SCF4-M-tps.png) For exact dimensions and locations check 3D STEP file.# Controlling SCF4 with G-code commands FIZ+ controller expects industry-standard G-code formatted commands. Commands are text-based and human-readable. Some highlights and behavior notes: - Controller has limited buffer/cache functionality, a user should rely on single command execution at a time. Each command ends with a response - Controller never sends commands back to the computer without asking - `G1` linear interpolation is not supported, but it can be implemented by setting motion speeds and feeds manually ## G-code introduction G-code is the common name for the most widely used numerical control (CNC) programming language. It tells the motors where to move, how fast to move, and what path to follow. G-code has many variants and each machine has unique behavior implementation. More details on G-code can be found at [https://en.wikipedia.org/wiki/G-code](https://en.wikipedia.org/wiki/G-code) ## Index of supported G-code commands Below is a list of supported commands. For a detailed explanation and usage examples see next section. ### Version strings and identification commands
**Command****Description****Returns**
`$S`Return version, sn, model and brand stringsSee details below
### Controller initialization
**Command****Description****Returns**
`$B1`Reset motor driver`OK`
`$B2`Reset and initialize motor driver`OK`
`$B3`Reset STM32F103 processor`OK`
### Motion commands
**Command****Description****Returns**
`G0`Rapid positionin`OK`
`G4`Wait / stallafter complete `OK`
`G90`Absolute programming mode`OK`
`G91`Incremental programming mode`OK`
`G92`Set position`OK`
### Miscellaneous function
**Command****Description****Returns**
`M0`Compulsory stop`OK`
`M7`DN function with filter (VIS)`OK`
`M8`DN function no filter (IR + VIS)`OK`
`M230`Set normal move`OK`
`M231`Set normal + forced move`OK`
`M232`Set PI low/high detection voltage`OK`
`M234`Set motor and DN drive current`OK`
`M235`Set motor idle current`OK`
`M238`PI LED on (some lenses leak light into sensor)`OK`
`M239`PI LED off`OK`
`M240`Set motor drive speed`OK`
`M245`Drive AUX output to low (high resistance output)`OK`
`M246`Drive AUX output to high (low resistance output)`OK`
`M247`Read power supply voltage value`ADC=xxxx`
### Advanced function
**Command****Description****Returns**
`M241`Dividing setting 1`OK`
`M242`Pulse generation control 1`OK`
`M243`Microstepping`OK`
`M244`Dividing setting 2`OK`
### Status commands
**Command****Description****Returns**
`!1`Return motor pos, limit sw, moving status`4000, 20000, 0, 0, 0, 0, 0, 0`
## Controlling SCF4 with G-code commands explanation and usage examples ### Axis description Driver support bipolar stepper motors for 3 axes. They are named A/B/C and usually have defined function: - A - zoom - B - focus - C - aperture ### `$S` - Return version string Command returns version string concentrated into single line `EVB.1.0.2, SCF4-M RevB, Kurokesu, 5DDFF39-3739584E-xxxxxxxx` received information is comma separated: - `EVB.1.0.2` - Module firmware version - `SCF4-M RevB` - Module PCB revision - `Kurokesu` - Manufacturer Brand - `5DDFF39-3739584E-xxxxxxxx` - Unique serial number ### `G0` - Rapid positioning The main motor drive command. It moves motor specified number steps. Any or all axes can be specified at the same time. Minimal step size is 1. `G0` command replies as soon as the command is parsed and does not wait until motors stop. - `G0 A100` - drives A-axis 100 steps - `G0 A-100` - drives A-axis -100 steps - `G0 A100 B-100 C1000` - drives all three axes by specified step count ### `G4` - Wait Instructs controller to delay (stall) defined interval in milliseconds \[ms\]. This is an only command which sends response not after parsing command but after prolonged execution time. During this time command parser is blocked and the only way to complete this command is to wait until it finishes. ### `G90` - Absolute coordinates Switch to absolute coordinate programming mode. In this mode, the range is limited by the internal 16-bit motor register and can be operated in a range of 0 ~ 65535. ### `G91` - Relative coordinates Switch to relative coordinate programming mode. Motors can be instructed to turn positive or negative 0 ~ 65535 steps (16-bits). When the counter exceeds this range, it will overflow. And will not affect motor movement. ### `G92` - Set position The controller sets an internal counter to the specified value. - `G92 A0` - Set A axis counter to 0 - `G92 A100` - Set A axis counter to 100 - `G92 A100 B1000 C200` - Set all axis counters to specified counter values ### `M0` - Compulsory stop If the controller is not in G4 delay mode it will instruct motors to stop moving ### `M7` and `M8` - Infrared filter switch commands Instructs controller to shift filter to one of two fixed positions ### `M230` and `M231` - normal / forced move - Default is normal mode in which motors turn instructed step count and stop after - In forced mode controller does not stop turning motor after specified step count is reached, instead seeks corresponding port PIN\_x status state change. Internal step counter may overflow. Motion is stopped when input status changes, `M0` or reset command is issued. PIN\_x is connected to internal 12bit Analog to Digital Converter (ADC), lower and upper thresholds can be controlled with `M232` command ### `M232` - Set PI low/high detection voltage Set 12bit comparator values for limit switch detection inputs. Upper voltage is 3.3V, lower - 0V - A, B, C - set lower threshold values - E, F, G - set upper threshold values - `M232 A1242 E2483` - If the input voltage is below ~1V - set flag to `0`. If the value is above ~2V, set flag to `1`. Everything in between - is hysteresis and does not change the flag. Used to debounce and filter the input signal ### `M234` - Set motor and DN drive current Sets motor and coil drive current. Expects 8-bit value. - `M234 A120 B120 C120 D80` - Set A, B, C stepper motors strength to 120 and IR filter driver to 80 ### `M235` - Set motor idle current When motors are not moving, idle current can be reduced to eliminate heating and save energy. It is not advised to completely turn off motors as the driver can lose micro-step holding position - `M234 A50 B50 C50` - Sets A/B/C motors holding current to value 50 ### `M238` and `M239` - control output pins Opto-interrupter LEDs can be controlled by connecting them to PIS\_AB and PIS\_C pins. They can stay in either state, but some lenses in IR mode can leak light into the sensor so after referencing/calibration procedure is complete it is advised to switch them off ### `M240` - Set motor drive speed Each motor can drive at different speeds. Speed is 16-bit register. Register specifies internal timing interval, the lower value is the faster pulse rate will be. - `M240 A800 B800 C1200` - Set motion speeds for each axis to corsponding value ### `M241`, `M242`, `M243`, `M244` - advanced timing registers - These registers control motor driver timing and should not be altered normally, however in some cases it can be necessary to make adjustments. Please seek the support if you have any questions ### `M245` - Drive AUX output to low Command drives auxiliary output to high resistance state. This is default value after power up or CPU reset.

Feature added in EVB.1.1.0 firmware. Used in **SCF4-L090 revC** and **SCF4-L087 revB** boards.

### `M246` - Drive AUX output to high Command drives auxiliary output to low resistance state.

Feature added in EVB.1.1.0 firmware. Used in **SCF4-L090 revC** and **SCF4-L087 revB** boards.

### `M247` - Read power supply voltage value Command reads power supply voltage. Responds with 12bit decimal value. Reference voltage is Vref=3.3
**Symbol****Value****Units****Note**
Vref3.3V
ADC\_TOP4096 12bit max ADC value
SCALE0.5 Boards uses resistance divider
ADC Value returned by command
Conversion to voltage: Vin = ADC/4096\*Vref/DIV

Feature added in EVB.1.1.0 firmware. Used in **SCF4-L090 revC** and **SCF4-L087 revB** boards.

### `!1` - Return status Command returns 9 values indicating: - `4000, 20000, 0, 0, 0, 0, 0, 0` - example output - A Motor position counter - B Motor position counter - C Motor position counter - A Limit switch status - B Limit switch status - C Limit switch status - A Moving status - B Moving status - C Moving status# Controlling over I2C port

Applies to EVB.1.2.0 firmware where I2C is implemented

Slave address: 0x33

#### About In order to simplify I2C communication, firmware utilizes one one direction read/write operations. All commands expect 5 bytes, where first byte is function address, remaining bytes is payload. USB-CDC works in parallel with I2C functionality and independently, but it is recommended to use single communication channel once controller is initialized. #### Wiring [![MFPi2c_connection.png](https://wiki.kurokesu.com/uploads/images/gallery/2020-08/scaled-1680-/MFPi2c_connection.png)](https://wiki.kurokesu.com/uploads/images/gallery/2020-08/MFPi2c_connection.png)

In order to avoid power loops, do not connect both (SCF4 and Arduino) USB ports at the same time.

#### Write data All commands are fixed length consisting of 5 bytes.
W: I2C ADDRFUNCTIONBYTE1BYTE2BYTE3BYTE4
#### Read data First issue write command (register values are ignored). This step performs necessary calculations and fills memory with registers ready for reading in next step.
W: I2C ADDRFUNCTIONBYTE1BYTE2BYTE3BYTE4
Read command also consists of 5 bytes. FUNCTION repeats last write command value.
R: I2C ADDRFUNCTIONBYTE1BYTE2BYTE3BYTE4
#### Commands
**ADDR****REGISTER NAME****R/W****FUNCTION**
0x02**RESET\_CPU**WReset STM32 CPU
0x03**INIT\_DRV**WReset and initialize motor driver
0x05**AUX\_OUT**WControl AUX output on/off
0x06**MODE** WNormal / forced move
0x07**STOP** WCompulsory stop
0x08**PI\_LEDS** WSwitch on ON or OFF PI LEDs
0x09**MOTOR\_SLEEP\_PWR** WSet motor sleep power
0x0A**MOTOR\_DRV\_PWR** WSet motor working power
0x0B**MOTOR\_SPEED** WSet motor speed
0x0C**PI\_THRESHOLD** WSet PI detector thresholds
0x0D**READ\_STATUS** RRead controller status
0x0E**SET\_MOTOR\_POS** WSet current motor position
0x0F**SET\_MICROSTEPPING**WSet motor micro-stepping mode
0x10**DN\_SWITCH**WIR fitler
0x20**MOVE**WMove motor
#### Command explanation ##### `RESET_CPU` - Reset CPU Resets CPU. Other values are ignored.
**Description****FUNCTION****BYTE1****BYTE2****BYTE3****BYTE4**
Reset CPU0x02ignoredignoredignored**0x32**
##### `INIT_DRV` - Reset motor driver Resets and initializes motor controller. Other values are ignored.
**Description****FUNCTION****BYTE1****BYTE2****BYTE3****BYTE4**
Initialize motor driver0x03ignoredignoredignored**0x32**
##### `AUX_OUT` - Control AUX output Controls GPIO output
**Description****FUNCTION****BYTE1****BYTE2****BYTE3****BYTE4**
Set AUX to Low0x05ignoredignoredignored**0x00**
Set AUX to High0x05ignoredignoredignored**0x01**
##### `MODE` - Normal / forced move Selects between normal and normal+forced move mode
**Description****FUNCTION****BYTE1****BYTE2****BYTE3****BYTE4**
Normal move mode0x06ignoredignored**Channel****0x00**
Normal+Forced move mode0x06ignoredignored**Channel****0x01**
Channel encoding:
**Channel****BYTE3 value**
A0x01
B0x02
C0x03
##### `STOP` - Compulsory stop Stop movement of all motors
**Description****FUNCTION****BYTE1****BYTE2****BYTE3****BYTE4**
Reset CPU0x07ignoredignoredignored**0x32**
##### `PI_LEDS` - Switch on ON or OFF PI LEDs Control LEDs used in homing procedure.
**Description****FUNCTION****BYTE1****BYTE2****BYTE3****BYTE4**
OFF0x08ignoredignoredignored**0x00**
ON0x08ignoredignoredignored**0x01**
##### `MOTOR_SLEEP_PWR` - Set motor sleep power Set motor sleep current
**Description****FUNCTION****BYTE1****BYTE2****BYTE3****BYTE4**
Set current0x09ignoredignored**Channel****Power**
Channel encoding:
**Channel****BYTE3 value**
A0x01
B0x02
C0x03
##### `MOTOR_DRV_PWR` - Set motor working power Set motor operating current
**Description****FUNCTION****BYTE1****BYTE2****BYTE3****BYTE4**
Set current0x0Aignoredignored**Channel****Power**
Channel encoding:
**Channel****BYTE3 value**
A0x01
B0x02
C0x03
D0x04
##### `MOTOR_SPEED` - Set motor speed Set motor speed
**Description****FUNCTION****BYTE1****BYTE2****BYTE3****BYTE4**
Set speed0x0Bignored**Channel****Speed \[15:8\]** **Speed \[7:0\]**
Channel encoding:
**Channel****BYTE2 value**
A0x01
B0x02
C0x03
##### `PI_THRESHOLD` - Set PI detector thresholds Set limit switch optocoupler detector thresholds
**Description****FUNCTION****BYTE1****BYTE2****BYTE3****BYTE4**
Set threshold0x0Cignored**Channel****Signal \[15:8\]** **Signal \[7:0\]**
Channel encoding:
**Channel****BYTE2 value**
A LOW0x01
B LOW0x02
C LOW0x03
A HIGH0x04
B HIGH0x05
C HIGH0x06
##### `READ_STATUS` - Read controller status Read motor status, PI status and motor positions
**Description****FUNCTION****BYTE1****BYTE2****BYTE3****BYTE4**
Set current0x0Dignoredignoredignored**Channel**
Channel encoding:
**Channel****BYTE2 value**
A position0x01
B position0x02
C position0x03
PI\_A status0x04
PI\_B status0x05
PI\_C status0x06
A moving0x07
B moving0x08
C moving0x09
Returns:
**Description****FUNCTION****BYTE1****BYTE2****BYTE3****BYTE4**
Status return value0x0D**Value \[31:24\]****Value \[23:16\]****Value \[15:8\]****Value \[7:0\]**
##### `SET_MOTOR_POS` - Set position Redefine current position
**Description****FUNCTION****BYTE1****BYTE2****BYTE3****BYTE4**
Set position0x0E**Channel****Speed \[23:16\]****Speed \[15:8\]** **Speed \[7:0\]**
Channel encoding:
**Channel****BYTE1 value**
A0x01
B0x02
C0x03
##### `SET_MICROSTEPPING` - Set microstepping mode Set microstepping mode for defined channel
**Description****FUNCTION****BYTE1****BYTE2****BYTE3****BYTE4**
Set microstepping0x0Fignoredignored**Channel** **Mode**
Channel encoding:
**Channel****BYTE1 value**
A0x01
B0x02
C0x03
##### `MOVE` - Move motor Move motor defined step count.
**Description****FUNCTION****BYTE1****BYTE2****BYTE3****BYTE4**
Steps0x20**Channel****Direction****Steps \[15:8\]** **Steps \[7:0\]**
Channel encoding:
**Channel****BYTE2 value**
A0x01
B0x02
C0x03

MAX steps is: 0xFFFF-1 = **0xFFFE**

Theia lens exceeds 0xFFFF step count, thus absolute positioning has to be implemented on client side code

##### `DN_SWITCH` - IR filter swith Switch filter to day or night position
**Description****FUNCTION****BYTE1****BYTE2****BYTE3****BYTE4**
POS10x10ignoredignoredignored**0x00**
POS20x10ignoredignoredignored**0x01**
#### Arduino sketch example Demo output should look like ```shell SCF4-M I2C tester Init driver Set microstepping Move mode PI LEDS Set drive pwr Set sleep pwr Set motor speeds Set PI thresholds Read status: posA D 0 0 0 0 Read status: PI A D 0 0 0 1 Homing A Homing B Move +A Move -A Move +B Move -B Move +C Move -C Set position DN 0 DN 1 DN 0 DN 1 Last return from I2C port: ok Loop... ``` `tester.ino` ```C #include #define CH_A 0x01 #define CH_B 0x02 #define CH_C 0x03 #define CH_D 0x04 #define CCW 0 #define CW 1 void err_print(byte err) { if (err == 0) { Serial.println("ok"); } else if (err==4) { Serial.println("failed"); } } void setup() { Wire.begin(); Serial.begin(115200); while (!Serial); Serial.println("\nSCF4-M I2C tester\n"); } void loop() { byte error; Serial.println("Init driver"); SCF4_INIT_DRIVER(); Serial.println("Set microstepping"); SCF4_MICROSTEPPING(2, CH_A); SCF4_MICROSTEPPING(2, CH_B); SCF4_MICROSTEPPING(6, CH_C); Serial.println("Move mode"); SCF4_MODE(0x00, CH_A); SCF4_MODE(0x00, CH_B); SCF4_MODE(0x00, CH_C); Serial.println("PI LEDS"); SCF4_PI_LEDS(0x01); Serial.println("Set drive pwr"); SCF4_DRV_PWR(180, CH_A); SCF4_DRV_PWR(180, CH_B); SCF4_DRV_PWR(180, CH_C); SCF4_DRV_PWR(90, CH_D); Serial.println("Set sleep pwr"); SCF4_SLEEP_PWR(50, CH_A); SCF4_SLEEP_PWR(50, CH_B); SCF4_SLEEP_PWR(50, CH_C); Serial.println("Set motor speeds"); SCF4_MOTOR_SPEED(5000, CH_A); SCF4_MOTOR_SPEED(5000, CH_B); SCF4_MOTOR_SPEED(5000, CH_C); Serial.println("Set PI thresholds"); SCF4_PI_THRESHOLD(2000, 0x01); SCF4_PI_THRESHOLD(2000, 0x02); SCF4_PI_THRESHOLD(2000, 0x03); SCF4_PI_THRESHOLD(3000, 0x04); SCF4_PI_THRESHOLD(3000, 0x05); SCF4_PI_THRESHOLD(3000, 0x06); Serial.println("Read status: posA"); SCF4_READ_STATUS(0x01); Serial.println("Read status: PI A"); SCF4_READ_STATUS(0x04); Serial.println("Homing A"); MOVE(30000, CW, CH_A); delay(2000); SCF4_MODE(0x01, CH_A); MOVE(0x100, CCW, CH_A); delay(15000); // status reading is not implemented, for testing 15s timeout is used SCF4_MODE(0x00, CH_A); SET_MOTOR_POS(100, CH_A); Serial.println("Homing B"); MOVE(30000, CW, CH_B); delay(2000); SCF4_MODE(0x01, CH_B); MOVE(0x100, CCW, CH_B); delay(15000); // status reading is not implemented, for testing 15s timeout is used SCF4_MODE(0x00, CH_B); SET_MOTOR_POS(100, CH_B); // normal operation starts here Serial.println("Move +A"); MOVE(0xFFFE, CW, CH_A); delay(5000); Serial.println("Move -A"); MOVE(0xFFFE, CCW, CH_A); delay(5000); Serial.println("Move +B"); MOVE(0xFFFE, CW, CH_B); delay(5000); Serial.println("Move -B"); MOVE(0xFFFE, CCW, CH_B); delay(5000); Serial.println("Move +C"); MOVE(1000, CW, CH_C); delay(2000); Serial.println("Move -C"); MOVE(1000, CCW, CH_C); delay(2000); Serial.println("Set position"); //SET_MOTOR_POS(100, 0x01); //SET_MOTOR_POS(200, 0x01); //SET_MOTOR_POS(300, 0x01); //STOP(); Serial.println("DN 0"); DN_SWITCH(0); delay(1000); Serial.println("DN 1"); DN_SWITCH(1); delay(1000); Serial.println("DN 0"); DN_SWITCH(0); delay(1000); Serial.println("DN 1"); DN_SWITCH(1); delay(1000); Serial.print("Last return from I2C port: "); err_print(error); Serial.println("Loop..."); while(1) { } } ``` `scf4_i2c.ino` ```C // SCL - A5 // SDA - A4 #include #define SCF4_ADDR 0x33 // SCF4 is not signaling busy status, thus fixed delay is added // If next I2C command is sent too soon it might be ignored #define I2C_SLEEP 200 byte SCF4_AUX(byte status) { byte function = 0x05; byte error; //byte w1 = (counter&0xFF); //byte w2 = ((counter>>8)&0xFF); //byte w3 = ((counter>>16)&0xFF); //byte w4 = ((counter>>24)&0xFF); Wire.beginTransmission(SCF4_ADDR); Wire.write(function); Wire.write(0); Wire.write(0); Wire.write(0); Wire.write(status); error = Wire.endTransmission(); delay(I2C_SLEEP); return error; } byte SCF4_RESET_CPU(void) { byte function = 0x02; byte error; Wire.beginTransmission(SCF4_ADDR); Wire.write(function); Wire.write(0); Wire.write(0); Wire.write(0); Wire.write(0x32); error = Wire.endTransmission(); delay(I2C_SLEEP); return error; } byte SCF4_INIT_DRIVER(void) { byte function = 0x03; byte error; Wire.beginTransmission(SCF4_ADDR); Wire.write(function); Wire.write(0); Wire.write(0); Wire.write(0); Wire.write(0x32); error = Wire.endTransmission(); delay(I2C_SLEEP); return error; } byte SCF4_MODE(byte mode, byte ch) { byte function = 0x06; byte error; Wire.beginTransmission(SCF4_ADDR); Wire.write(function); Wire.write(0); Wire.write(0); Wire.write(ch); Wire.write(mode); error = Wire.endTransmission(); delay(I2C_SLEEP); return error; } byte SCF4_PI_LEDS(byte mode) { byte function = 0x08; byte error; Wire.beginTransmission(SCF4_ADDR); Wire.write(function); Wire.write(0); Wire.write(0); Wire.write(0); Wire.write(mode); error = Wire.endTransmission(); delay(I2C_SLEEP); return error; } byte SCF4_SLEEP_PWR(byte pwr, byte ch) { byte function = 0x09; byte error; Wire.beginTransmission(SCF4_ADDR); Wire.write(function); Wire.write(0); Wire.write(0); Wire.write(ch); Wire.write(pwr); error = Wire.endTransmission(); delay(I2C_SLEEP); return error; } byte SCF4_DRV_PWR(byte pwr, byte ch) { byte function = 0x0A; byte error; Wire.beginTransmission(SCF4_ADDR); Wire.write(function); Wire.write(0); Wire.write(0); Wire.write(ch); Wire.write(pwr); error = Wire.endTransmission(); delay(I2C_SLEEP); return error; } byte SCF4_MOTOR_SPEED(int speed, byte ch) { byte function = 0x0B; byte error; Wire.beginTransmission(SCF4_ADDR); Wire.write(function); Wire.write(0); Wire.write(ch); Wire.write(highByte(speed)); Wire.write(lowByte(speed)); error = Wire.endTransmission(); delay(I2C_SLEEP); return error; } byte SCF4_PI_THRESHOLD(int level, byte ch) { byte function = 0x0C; byte error; Wire.beginTransmission(SCF4_ADDR); Wire.write(function); Wire.write(0); Wire.write(ch); Wire.write(highByte(level)); Wire.write(lowByte(level)); error = Wire.endTransmission(); delay(I2C_SLEEP); return error; } byte SCF4_READ_STATUS(byte ch) { byte function = 0x0D; byte error; /* * channel: * 0x00 - dummy, reads 0x87, 0x65, 0x43, 0x21 * 0x01 - chA.position * 0x02 - chB.position * 0x03 - chC.position * 0x04 - piA.status * 0x05 - piB.status * 0x06 - piC.status * 0x07 - chA.moving * 0x08 - chB.moving * 0x09 - chC.moving */ Wire.beginTransmission(SCF4_ADDR); Wire.write(function); Wire.write(0); Wire.write(0); Wire.write(0); Wire.write(ch); error = Wire.endTransmission(); delay(I2C_SLEEP); byte w1 = 0xff; byte w2 = 0xff; byte w3 = 0xff; byte w4 = 0xff; byte w5 = 0xff; Wire.requestFrom(SCF4_ADDR, 5); w1 = Wire.read(); w2 = Wire.read(); w3 = Wire.read(); w4 = Wire.read(); w5 = Wire.read(); Serial.print(w1, HEX); Serial.print(" "); Serial.print(w2, HEX); Serial.print(" "); Serial.print(w3, HEX); Serial.print(" "); Serial.print(w4, HEX); Serial.print(" "); Serial.print(w5, HEX); Serial.println(); delay(I2C_SLEEP); // TODO: return read values return error; } byte SET_MOTOR_POS(int pos, byte ch) { byte function = 0x0E; byte error; Wire.beginTransmission(SCF4_ADDR); Wire.write(function); Wire.write(ch); Wire.write(0); Wire.write(highByte(pos)); Wire.write(lowByte(pos)); error = Wire.endTransmission(); delay(I2C_SLEEP); return error; } byte MOVE(unsigned int steps, byte dir, byte ch) { byte function = 0x20; byte error; Wire.beginTransmission(SCF4_ADDR); Wire.write(function); Wire.write(ch); Wire.write(dir); Wire.write(highByte(steps)); Wire.write(lowByte(steps)); error = Wire.endTransmission(); delay(I2C_SLEEP); return error; } byte DN_SWITCH(byte mode) { byte function = 0x10; byte error; Wire.beginTransmission(SCF4_ADDR); Wire.write(function); Wire.write(0); Wire.write(0); Wire.write(0); Wire.write(mode); error = Wire.endTransmission(); delay(I2C_SLEEP); return error; } byte SCF4_MICROSTEPPING(byte stepping, byte ch) { byte function = 0x0F; byte error; Wire.beginTransmission(SCF4_ADDR); Wire.write(function); Wire.write(0); Wire.write(0); Wire.write(ch); Wire.write(stepping); error = Wire.endTransmission(); delay(I2C_SLEEP); return error; } byte STOP(void) { byte function = 0x07; byte error; Wire.beginTransmission(SCF4_ADDR); Wire.write(function); Wire.write(0); Wire.write(0); Wire.write(0); Wire.write(0x32); error = Wire.endTransmission(); delay(I2C_SLEEP); return error; } ```# Demonstration software ## Overview SCF4-SDK comes with open-sourced command line and GUI sample programs for rapid controller evaluation. A simple control software example is provided for testing and demonstration. Software is given "as is" to help with getting started and testing. Source code is maintained on [GitHub](https://github.com/Kurokesu/SCF4-SDK) There are several control software branches maintained in parallel for different cameras. See table below for details
**Camera / Product****Controller board****Notes**
[C1\_PRO\_X18](https://www.kurokesu.com/shop/C1_PRO_X18)SCF4-L087Camera block with 18x motorized zoom lens
[C1\_PRO\_X20](https://www.kurokesu.com/shop/C1_PRO_X20)SCF4-L090Camera block with 20x motorized zoom lens
[C1\_PRO\_X10](https://www.kurokesu.com/shop/C1_PRO_X10)SCF4-L054Camera with 10x motorized zoom lens
[C1\_PRO\_X3](https://www.kurokesu.com/shop/C1_PRO_X3)SCF4-L050Camera with 3x motorized zoom lens
[SCF4-L065-KIT](https://www.kurokesu.com/shop/SCF4-L065-KIT)SCF4-EVB5-50mm lens with M14/CS mount
[SCF4-L002-KIT](https://www.kurokesu.com/shop/SCF4-L002-KIT)SCF4-EVB2.8-12mm lens with M14/CS mount
## GUI Python program with a graphical user interface allows many parameters to be controlled by an inexperienced user. To keep user interface uncluttered some parameters are not displayed. After connecting to SCF4 controller virtual serial port version string should be displayed at the bottom. Also, all controls will be activated. From now relative movement commands should be issued to check if connected motors turn properly (once button is pressed it will change positioning mode to absolute). When sliders operated positioning is switched to absolute mode, it makes sense after the axis is referenced. Python scripting language with PyQt5 user interface was chosen because of rapid development and clear syntax. Python 3.6 and a few dependencies should be installed before running any examples. Python and PyQt5 enables modern cross-platform user interface capable of running on high DPI monitors correctly. [![5uXscf4-m_gui_demo.png](https://wiki.kurokesu.com/uploads/images/gallery/2020-08/scaled-1680-/5uXscf4-m_gui_demo.png)](https://wiki.kurokesu.com/uploads/images/gallery/2020-08/5uXscf4-m_gui_demo.png) Many lenses and motion systems can be connected to the controller and they can be split into two groups - with and without limit/reference switch/sensor. So there are two fundamentally different homing approaches. 1. Homing without limit switch is not very accurate but universal and works with all lenses. Idea is to rotate motor until the mechanical system hits its limit, then rotate a bit backwards and mark position as `0`. The lens should not sustain any irreversible damage, but this procedure should not be performed often. 2. The lens can incorporate various limit or reference switch configurations, therefore homing procedure should be adapted to a particular geometry. For example, the lens has reference opto-interrupter when it crosses the middle of its travel. By reading status register it becomes is clear at which section lens axis is and motor should be moved to center until switch changes status. To complicate things even more optocoupler or any switch has backlash/hysteresis and controller comparator has adjustable lower and upper thresholds. Good understanding of how particular lens behaves is a must and still, it can take a few experiments to set optimal parameters. Some lenses depending on each axis position can have variable travel limits. Current program version has following homing procedure implemented: - Move motor by a fixed number of steps (lens may hit mechanical stop) - Move opposite direction until the switch is actuated - Move back by a fixed number of steps - Set current position as 0 Program configuration is saved to `settings.json`. It's a read/write file with the purpose to provide default settings for some parameters like motion speed, jog steps, last used COM port, etc. and save settings and last position when program is closed. Internal stepper motor driver has 16-bit position counter, absolute positioning is possible within a range of 0..65535 steps, (for 200 steps per revolution motor equals 20 full turns). In relative movement, if motion exceeds 16bit counter range it will overflow and continue the motion. The single move command is also 16 bits. ## Command line Command-line programs provide quick clean coding templates, examples to understand G-code usage. Programs explain how to: - Read version string - Initialize and perform relative movements - Perform lens homing - Change motion speed - Perform an emergency stop - And more For the full list see the examples directory ## Terminal Control commands also can be sent directly from a terminal program of your choice. Baudrate for virtual COM port is irrelevant and communication speed over Full-speed USB 2.0 is 12 Mbit/s. - Each command must be terminated by a newline - Each command returns status code or requested information# Drivers #### Drivers Stock firmware registers as "STM32 Virtual COM". Most modern operating systems should work out of the box, but original drivers can be downloaded from [STMicroelectronics web page](https://www.st.com/en/development-tools/stsw-stm32102.html)

In some Windows cases Prolific USB to serial controller drivers can claim detected COM port, in this case uninstall driver and install downloaded from ST web page.

# Dedicated boards Kurokesu SCF4 multi-axis stepper motor controller System On Module (SOM) targets applications where time to market, reliability and small footprint is important. Main control MCU is ST Cortex STM32F103 powerful enough either to run standard or run dedicated standalone firmware. The motor front end is based on ON Semiconductor new and highly specialized driver [LC898201](https://www.onsemi.com/products/power-management/motor-drivers/motor-drivers-stepper/lc898201). Besides SCF4-M module, some basic boards are offered #### SCF4-BREAKOUT breakout demo board **SCF4 BREAKOUT** board allows quick evaluation, testing and prototyping. ##### General view[![Kurokesu-SCF4-breakout-1.jpg](https://wiki.kurokesu.com/uploads/images/gallery/2021-01/scaled-1680-/Kurokesu-SCF4-breakout-1.jpg)](https://wiki.kurokesu.com/uploads/images/gallery/2021-01/Kurokesu-SCF4-breakout-1.jpg) ##### Schematics ##### ![sch_sce2_breakout.png](https://wiki.kurokesu.com/uploads/images/gallery/2021-02/scaled-1680-/sch_sce2_breakout.png) ##### PCB Layers [![layers.png](https://wiki.kurokesu.com/uploads/images/gallery/2021-02/scaled-1680-/layers.png)](https://wiki.kurokesu.com/uploads/images/gallery/2021-02/layers.png) #### SCF4-THEIA lens controller board **SCF4-THEIA** board is designed for THEIA motorized zoom lenses: [TL410P R6](https://www.theiatech.com/tl410-4k-resolution) and [TL1250P R6](https://www.theiatech.com/tl1250-4k-telephoto) ##### General view[![IMG_2843_r.jpg](https://wiki.kurokesu.com/uploads/images/gallery/2021-02/scaled-1680-/IMG_2843_r.jpg)](https://wiki.kurokesu.com/uploads/images/gallery/2021-02/IMG_2843_r.jpg) ##### Schematics [![SCH_SCE2_THEIA_1of2.png](https://wiki.kurokesu.com/uploads/images/gallery/2021-02/scaled-1680-/SCH_SCE2_THEIA_1of2.png)](https://wiki.kurokesu.com/uploads/images/gallery/2021-02/SCH_SCE2_THEIA_1of2.png) [![SCH_SCE2_THEIA_2of2.png](https://wiki.kurokesu.com/uploads/images/gallery/2021-02/scaled-1680-/SCH_SCE2_THEIA_2of2.png)](https://wiki.kurokesu.com/uploads/images/gallery/2021-02/SCH_SCE2_THEIA_2of2.png) ##### Typical power profile [![scf4_theia_power_profile.png](https://wiki.kurokesu.com/uploads/images/gallery/2021-06/scaled-1680-/scf4_theia_power_profile.png)](https://wiki.kurokesu.com/uploads/images/gallery/2021-06/scf4_theia_power_profile.png) ##### PCB layers [![LOulayers.png](https://wiki.kurokesu.com/uploads/images/gallery/2021-02/scaled-1680-/LOulayers.png)](https://wiki.kurokesu.com/uploads/images/gallery/2021-02/LOulayers.png) #### SCF4-EVB D14 motorized zoom lens controller board Stepper motor controller evaluation board **SCF4-EVB** is designed to demonstrate **SCF4-M** module capabilities. It can drive two different types of Focus/Zoom/P-Iris lenses. Can be used as a complete product, easily redesigned to drive other lens or fit specific needs. ##### General view [![scf4-evb.jpg](https://wiki.kurokesu.com/uploads/images/gallery/2021-03/scaled-1680-/scf4-evb.jpg)](https://wiki.kurokesu.com/uploads/images/gallery/2021-03/scf4-evb.jpg) ##### Schematics [![SCF4-EVB-sch.png](https://wiki.kurokesu.com/uploads/images/gallery/2021-07/scaled-1680-/SCF4-EVB-sch.png)](https://wiki.kurokesu.com/uploads/images/gallery/2021-07/SCF4-EVB-sch.png) ##### Features - Small footprint 42 x 33 x 4.6 mm \[1.65 x 1.3 x 0.18 in\] - Supports two kinds of lenses - 3x stepper motor controller with up to 1/1024 micro stepping support for each motor (1/64 set by default) - 1x H-bridge for coil control (day/night filter switch) - 2x limit switch processing for precise lens homing/referencing (3x supported by module) - Direct Full-speed micro USB 2.0 - Optional USART connectivity / GPIO# Precautions and disclaimers ## General disclaimer - ALL PRODUCTS, PRODUCT SPECIFICATIONS, AND DATA ARE SUBJECT TO CHANGE WITHOUT NOTICE TO IMPROVE RELIABILITY, FUNCTION OR DESIGN OR OTHERWISE - Kurokesu UAB, its affiliates, agents, and employees, and all persons acting on its or their behalf (collectively, "Kurokesu"), disclaim any and all liability for any errors, inaccuracies or incompleteness contained in any datasheet or any other disclosure relating to any product. - The Information given herein is believed to be accurate and reliable. However, users should independently evaluate the suitability of and test each product selected for their applications - See Kurokesu standard terms and conditions for warranty and other information ## Precautions - Do not short circuit any part of the module - Do not exceed nominal input - Do not overload outputs - Keep the module dry - Observe the electrostatic discharge (ESD) precautions when handling the product. Damage caused by non-observance of the above instructions is not covered by the warranty - Power electronics equipped with thermal shutdown circuitry, but if controller becomes too hot disconnect it - Module is designed exclusively for installation into a device or housing to prevent external influences such as humidity/water or dirt - Add active and/or passive power filtering circuitry in an electromagnetically noisy environment if a module becomes unstable - Add active and/or passive power filtering circuitry if module exceeds allowed EMC emissions# Revisions ## Documentation revision history
**Version****Date****Changes**
0.12019-07-01Initial documentation created
1.02019-07-22Internal release
1.12019-07-22Disclaimers and precautions added, more complete command description added
1.22019-07-23Minor corrections and mistypes, document public release
1.32020-07-27Migrated to online documentation. Lens section moved to separate document.
1.42020-08-09Added documentation parts affected by EVB.1.1.0 new firmware features, fixed a few typos, minor updates
1.52020-08-15Added I2C documentation
1.62021-02-07Updated some pictures, added more demonstration board details
## Firmware revision history
**Version** **Date****Changes**
0.6.522019-07-01- Initial public release version
EVB.1.0.02019-07-14- Bump to 1.0.0 release - Consolidated version reporting into single string - Code cleanup
EVB.1.0.12019-07-14- Minor bug fixes
EVB.1.0.22019-07-18- Added new advanced commands: M241..M244 - Fixed: set motor idle power to 0 is not allowed - Fixed: default relative movement mode after reset
EVB.1.1.02020-05-30- Added USART support over 4 pin connector besides original USB-CDC mode
EVB.1.2.02020-08-15- Added I2C support (forked from EVB.1.1.0)
EVB.1.3.02020-08-09- Added power input voltage ADC readout command - Added AUX output on/off control commands