Prerequisites
Required hardware:
Task
Control of 2 motors using I2C interface.
Hookup
- Do not connect battery yet.
- Use ML-R Cable KK254-KK254 20 cm (mrm-kk2.54-2.54-20) and connect 3.3 V voltage output to driver's voltage input (any orange connector). If You have some other power supply, use 2 Dupont 0.1" wires to deliver 3.3 V DC to any of the 2 orange connectors. Mind + and -! The driver has reverse input voltage protection, but it is better not to test it. At least, the board will not work, if voltage is reversed.
- Take 2 Dupont cables and connect 5 V voltage output to Mega 2560 "5V" input. This action will deliver voltage to Mega 2560 internal linear regulator's output, skipping Mega 2560 protection, but MRMS Power Supply 3x (mrm-ps3x) has the protection built-in. Doing so will replace an inefficient linear regulator with a switching step-down regulator. If You do not have 5 V DC voltage source, You can connect 7 - 12 V (battery output) directly to Mega 2560 pin "VIn".
- connect power supply and the driver with a ML-R Cable KK396-KK396 10 cm (mrm-kk3.96-3.96-10) or similar cable in order to deliver power to motors.
- Connect driver's pin "SCL" to Mega 2560 pin "SCL 21". Use a single Dupont wire.
- Connect driver's pin "SDA" to Mega 2560 pin "SDA 20". Use a single Dupont wire.
- Check all the polarities!
- Turn power switch off.
- Connect battery.
- Turn power switch on.
- Driver's green LED must blink 0.1 sec. every second. If so, You are good to go.
Even if You have some other type of hookup, make sure that the driver and Mega 2560 have common ground (GNDs connected).
Pull-up resistors
I2C demands pull-up resistors. Mega 2560 doesn't need them because it features internal 10 kΩ resistors. If You intend to use some other board, You may be forced to use external 2 - 10 kΩ pull-up resistors, connecting 3.3 V to both SCL and SDA, each with its own resistor.
Program
Here is Arduino program.
#include <Wire.h> // I2C library.
#define DATA_COUNT 1 // Number of bytes to receive.
#define I2C_ADDRESS 0x12 // Driver's I2C address.
#define REGISTER_FIRMWARE 0x01 // I2C virtual register containing firmware version.
#define REGISTER_ALL_SPEEDS 0x00 // I2C virtual register for settings speeds
uint32_t ms; // Variable used for displaying results periodically.
void setup() {
Serial.begin(115200); // Adjust monitor speed to 115200 bps in order not to get garbage in the window.
Wire.begin(); // Start I2C.
delay(500); // Wait to be sure that the text will be displayed.
Serial.println("Start");
Wire.beginTransmission(I2C_ADDRESS); // Start a "write" I2C command (write to driver).
Wire.write((uint8_t)REGISTER_FIRMWARE); // Send the desired virtual register address.
Wire.endTransmission(); // End "write" part.
Wire.requestFrom((int)I2C_ADDRESS, DATA_COUNT); // Start "read" part (read from sensor). Request 4 bytes of data.
uint8_t fw = Wire.read(); // Read firmware version.
Serial.println("FW: " + (String)fw + "."); // Display.
}
void loop() {
int8_t step = 1;
for (int8_t speed = 1; !(speed == 0 && step == 1); speed += step){ // This loop changes speed gradually. The logic is not important for the purpose of this exercise.
Wire.beginTransmission(I2C_ADDRESS); // Start a "write" I2C command (write to sensor).
Wire.write((uint8_t)REGISTER_ALL_SPEEDS); // Send the desired virtual register address.
for (uint8_t i = 0; i < 2; i++) // For all the 4 motors...
Wire.write((uint8_t)speed + 128); // Set speed. It is the same for all the motors. Add 128 to the speed to get the format needed for this command.
Wire.endTransmission(); // End "write" part.
delay(30); // Wait 30 ms in order not to change the speeds abruptly.
if (millis() - ms > 100){ // Every 0.1 sec...
Serial.println("Speed: " + (String)speed + "."); // Display.
ms = millis();
}
if (abs(speed) == 127) // Change rotation direction.
step = -step;
}
}
Upload the program, open Arduino monitor, and change baud rate to 115200. Output should look like in the picture left.
Disadvantages
I2C interface is rather simple, but it designed for on-board communication only, susceptible to surrounding noise and contact corrosion. To get a robust link, use CAN Bus inteface.