First start by defining what basic functions the library should perform for now at least for this first Hardware and Software version the library will be in charge of establishing the I2C connection with the Fab Motor Controller, plus two functions to activate and deactivate a given output.
- Establish I2C communication
- Activate a given output at a given speed
- Deactivate a given output
I have some functions in mind that I would like to implement in the future as a blocking function and another one to read the status of the outputs.
Now that I am clear about the functions I want to implement it is time to write the header file that contains the definitions and methods I am going to use.
The file looks like this.
/*
* FabMotorController.h v0.1
* A library to control through I2C the FabMotorController,
* a hardware based on the ATTINY1614 and the L298N driver.
*
* Author: Harley Lara
* Create: 01 May 2021
* License: (CC BY-SA 4.0) Attribution-ShareAlike 4.0 International
*
* This work may be reproduced, modified, distributed,
* performed, and displayed for any purpose, but must
* acknowledge this project. Copyright is retained and
* must be preserved. The work is provided as is; no
* warranty is provided, and users accept all liability.
*
*/
#ifndef _FABMOTORCONTROLLER_
#define _FABMOTORCONTROLLER_
#include
// Output identifiers
#define OUTPUT1 1
#define OUTPUT2 2
class FabMotorController{
private:
/******** Dirección de las salidas ********/
// 1: Forward
// 0: Backward
bool _OUT1_direction = 1;
bool _OUT2_direction = 1;
/******** Initial speed of the motors ********/
// _speed1 from 0 to 100;
unsigned char _speed1 = 0;
// _speed2 from 0 to 100;
unsigned char _speed2 = 0;
// I2C Controller address
unsigned char _addr = 0x04;
public:
// Initializes the I2C with a default I2C address (0x04)
int begin(unsigned char addr);
/******** Activates the output at a given speed ********/
// output: OUTPUT1, OUTPUT2
// _speed: from -100 to 100,
// where _speed greater than zero moves the motor clockwise
// (the direction of the motor depends on the physical connection
// of the motor, if it turns counterclockwise it is necessary to
// reverse the connection).
void run(unsigned char output, int _speed);
/******** Stops the given output by locking for 100ms the motor rotation and then releases the motor lock ********/
// output: OUTPUT1, OUTPUT2
void stop(unsigned char output);
/******** Stops motor rotation allowing it to run freely (no motor blocking) ********/
void stopLock(unsigned char output);
bool isMoving(unsigned char output);
};
#endif
Then it was necessary to write the main file containing the instructions to be executed by the library.
The file looks like this.
/*
* FabMotorController.cpp v0.1
* A library to control through I2C the FabMotorController,
* a hardware based on the ATTINY1614 and the L298N driver.
*
* Author: Harley Lara
* Create: 01 May 2021
* License: (CC BY-SA 4.0) Attribution-ShareAlike 4.0 International
*
* This work may be reproduced, modified, distributed,
* performed, and displayed for any purpose, but must
* acknowledge this project. Copyright is retained and
* must be preserved. The work is provided as is; no
* warranty is provided, and users accept all liability.
*
*/
#include "FabMotorController.h"
#include
/******** Initializes and sets the I2C address ********/
// addr: motor controller address (default 0x04)
int FabMotorController::begin(unsigned char addr){
if (addr != 0x04){
Serial.println("[ERROR]: Incorrect I2C address, default address 0x04.");
return -1; // Incorrect I2C address
}
Wire.begin();
delayMicroseconds(10000);
this -> _addr = addr;
Serial.println("[INFO]: I2C Initialization");
return 0; // Initialization completed without errors
}
/******** Activates the output at a given speed ********/
// output: OUTPUT1, OUTPUT2
// _speed: from -100 to 100,
// where _speed greater than zero moves the motor clockwise
// (the direction of the motor depends on the physical connection
// of the motor, if it turns counterclockwise it is necessary to
// reverse the connection).
void FabMotorController::run(unsigned char output, int _speed){
if (output < OUTPUT1 || output > OUTPUT2){
Serial.println("[ERROR]: Out of range, must be OUPUT1 or OUPUT2, or alternatively 1 or 2");
return;
}
if (output == OUTPUT1){
if (_speed >= 0){
this->_OUT1_direction = 1;
_speed = _speed > 100 ? 100 : _speed;
this->_speed1 = map(_speed, 0, 100, 0, 255);
} else if(_speed < 0){
this->_OUT1_direction = 0;
_speed = _speed < -100 ? 100 : -(_speed);
this->_speed1 = map(_speed, 0, 100, 0, 255);
}
// Send action OUTPUT 1
Serial.println("[INFO]: Sending Command to OUPUT1");
Wire.beginTransmission(this -> _addr); // Starts I2C transmission
Serial.println(_OUT1_direction);
Wire.write(OUTPUT1); // Set the output to be activated
Wire.write(this->_speed1); // Set the speed
Wire.write(this->_OUT1_direction); // Set the direction
Wire.endTransmission(); // Transmission stops
delay(4);
Serial.println("[INFO]: Command sent");
}else if(output == OUTPUT2){
if (_speed >= 0){
this -> _OUT2_direction = 1;
_speed = _speed > 100 ? 100 : _speed;
this -> _speed2 = map(_speed, 0, 100, 0, 255);
} else if(_speed < 0){
this -> _OUT2_direction = 0;
_speed = _speed < -100 ? 100 : -(_speed);
this->_speed2 = map(_speed, 0, 100, 0, 255);
}
// Send action OUTPUT 2
Serial.println("[INFO]: Sending Command to OUPUT2");
Wire.beginTransmission(this -> _addr); // Starts I2C transmission
Wire.write(OUTPUT2); // Set the output to be activated
Wire.write(this->_speed2); // Set the speed
Wire.write(this -> _OUT2_direction); // Set the direction
Wire.endTransmission(); // Transmission stops
delay(4);
Serial.println("[INFO]: Command sent");
}
}
void FabMotorController::stop(unsigned char output){
if (output < OUTPUT1 || output > OUTPUT2){
Serial.println("[ERROR]: Out of range, must be OUPUT1 or OUPUT2, or alternatively 1 or 2");
return;
}
run(output, 0);
}
At this point the library is ready.