Stepper Motor Controller (Prototype)

Stepper Motor Controller (Prototype)


NOTE: Please be aware that the Stepper Motor Controller board is currently in the prototype phase, and we are actively testing and refining its design. The final version of the board may differ from the prototype version.

The content provided here represents the initial experimental version of the board. For the latest design files and source code, please visit our GitHub page.

Motivation

The main motivation for this control board is to provide a user-friendly solution for prototyping devices utilizing stepper motors. The intention is to enable seamless control of the board by sending simple commands that dictate the motor’s direction, step count, and speed.

Our aim was to create a board that offers flexibility and independence from specific standards such as G Code. This should allow users to have freedom in designing and implementing their control systems.

To achieve this, the control board is designed to rely on the master device for handling acceleration, linear and/or circular interpolation. By breaking down complex instructions into simple commands that the board can understand, the master device retains control over these advanced functionalities. This approach empowers users to customize and optimize their control algorithms according to their specific requirements.

Overview

The Stepper Motor Controller board offers the capability to control the rotation direction, step count, and speed of up to four individual stepper motors simultaneously. To interact with the board, commands are sent through the I2C interface, Figure1 - 1.
While the board is designed to be connected to a Raspberry Pi, it can be easily connected to any device that supports I2C communication.

PNP Switch Circuit

Figure 1: Stepper Motor Controller board with wire diagram example for connecting a stepper motor
1 - I2C interface on pins 3 and 5 of the header connector
2 - Slide switch to switch the power source from Raspberry Pi board to external
3 - header connector to connect external power source
4 - pulse, header connector with direction, and limit switches pins for motor A
5 - pulse, header connector with direction, and limit switches pins for motor B
6 - pulse, header connector with direction, and limit switches pins for motor C
7 - pulse, header connector with direction, and limit switches pins for motor D

The Stepper Motor Controller board offers two options for powering: it can be powered either from the Raspberry Pi or from an external power source. A slide switch is provided to select between the two power options, Figure 1 - 2.
If you choose to power the board from an external source (using external connector J3, Figure 1 - 3), please ensure that you provide a regulated 5V power supply. The board itself does not have a built-in power regulator. Supplying inappropriate or unregulated power to the board can result in permanent damage or improper functionality.

The board incorporates an ATTiny826 microcontroller responsible for processing commands and generating the necessary signals for motor control. Note that the ATTiny826 microcontroller has a limited memory capacity of 8KB, which means it is not capable of storing a G Code interpreter like the Arduino’s ATMega32.

The initial design of the board includes four header connectors dedicated to each stepper motor, Figure 1 - 4, 5, 6, and 7. These connectors should be connected to compatible motor driver boards such as A4988, DRV8825, and others. Each connector has one pin for the steps signal, one pin for the direction signal, and two pins for the limit switches signal.

In typical projects, it is common for the signals from limit switches to be pulled to the ground. When a switch is activated, the corresponding signal is pulled up. However, for the current board, the configuration is slightly different.
On this board, when no switch is activated, the board expects the switch pin to be pulled-up. When a switch is activated, it should pull down the signal on the switch pin, indicating its activation.

The board incorporates an SN74LS148 chip, which provides 8 input lines. These lines are used to connect to the limit switches, and the chip encodes the signals into 4 bits. This encoding enables the ATTiny826 microcontroller to identify which limit switch is activated. In situations where two or more limit switches are simultaneously activated, the encoder prioritizes the highest-order data line.

Commands

A command is defined as a sequence of characters (a string) that is sent through the I2C interface to the board. Upon successful execution of a command, the board responds with an “OK” response, except in the case of the status command which has a separate behavior (see the “Status” section for details). In case of an error during command execution, the board provides a short error message as feedback.

Version command

Format: version
The version command returns a string that represents the current version of the board’s design and firmware.

Set address command

Format: setaddr:<address_value>
The address_value represents a value between 3 and 119.
The setaddr command is used to assign a new I2C slave address to the board. This feature allows for flexibility in I2C address assignment and avoids conflicts when multiple devices are connected on the same bus. The default I2C slave address for the board is 80 (0x50).

Status command

Format: status
The status command returns the following information:

  • Board state, indicates whatever the board is executing a run or move command, or is paused
  • The command details, such as the direction of movement, the remaining steps to be executed, and the current speed
  • The label of the activated limit switch if there is one activated
  • The number of available slots in the command buffer.

Run command

Format: run:<device_id[A,B,C, or D]>:<steps[+/- 32-bit integer]>,<speed[+16-bit integer]>:[<device_id[A,B,C, or D]>:<steps[+/- 32-bit integer]>,<speed[+16-bit integer]>]
The run command consists of one or more parts, each specifying a motor (A, B, C, or D), rotation direction, number of steps, and speed.
An user can control multiple motors simultaneously by including their respective parts in the command. For example, run:A-200,20:B130,35:C100,10:D200,20 will run all four motors together, while run:A-200,20:D200,20 will only rotate motors A and D. Specifying a positive value for steps rotates the motor in a clockwise direction, while a negative value indicates counter-clockwise rotation. The speed parameter allows adjustment of motor rotation speed. A value of 1 represents the maximum speed, while higher values slow down the motor. For example, specifying speed 2 will make the motor move at half the maximum speed. If multiple parts are provided for the same motor, the last part in the command will override any previous parts. For instance, run:A-200,20:A200,10:A1000,5 will rotate motor A 1000 steps clockwise with speed 5.

The values of the run command are stored in a command buffer, which operates as a queue. If the buffer is not empty, new commands will wait for the execution of previous commands. Users can send multiple commands sequentially, and they will be stored in the buffer.

If the board is in a paused state and the buffer is not full, new commands will be stored but not executed until the board is resumed. The command buffer has a capacity of 16 commands (90% of Data Memory Usage for the ATTiny826 chip). When the buffer is full, users will receive a BUFFER FULL message. Once slots become available in the buffer, more run commands can be sent.

If a limit switch is activated during execution, the board will pause further command execution. To deactivate a limit switch, use the move command.

Move command

Format: move:<device_id[A,B,C, or D]>:<steps[+/- 32-bit integer]>,<speed[+16-bit integer]>
The move command is a special command designed to move a single motor. It takes precedence over any ongoing run commands. The structure of the move command is similar to the run command, but it allows only one part to be specified. If multiple parts are provided, the move command will execute only the first part and ignore the rest.

The move command will pause any running commands on the board. Even if the board is in a paused state, the move command will still be executed.

If a new move command is sent while another move command is running, the new move command will override the ongoing move operation.

The move command is particularly useful for deactivating limit switches. When a move command is executed, the limit switch status will automatically update.

Pause command

Format: pause
The pause command is used to pause any ongoing commands that are currently running on the board. However, it does not affect the execution of move commands. If the board is already in a paused state, sending another pause command will have no effect.

Resume command

Format: resume
The resume command is used to resume the execution of commands that have been previously paused on the board. If the board is already in a running state, sending another resume command will have no effect.

Reset command

Format: reset
The reset command clears the command buffer and cancels any move command if currently running. Additionally, if the board is in the paused state, the reset command will switch the board in the running state.

Future improvements

As mentioned earlier, the Stepper Motor Controller board is currently in the prototype phase. We have several potential features and improvements in mind, but we don’t guarantee their inclusion in the final version.

To ensure consistency, we plan to update the PCB labels to clearly indicate which connectors correspond to each motor (A, B, C, or D). Additionally, we will modify the steps and direction labels for each motor, such as changing “Step1” to “Step A” and “Dir1” to “Dir A.” Similarly, the limit switch labels will be updated from “SW0” to “A+”, “SW1” to “A-”, “SW2” to “B+”, and so on.

We are considering experimenting with the addition of sockets for motor driver boards, similar to the setup found on the CNC Shield board for Arduino Uno. This would involve rearranging components and incorporating connector sockets for improved flexibility.

We may remove the external power source connector and switch from the board. Since the control board itself should not consume a significant amount of power, it may not require a separate power source.

Furthermore, we are exploring the integration of the board with FibStack CLI and Dashboard. This integration would enable users to interact with the board seamlessly when connected to a Raspberry Pi