Hi,
I am following a thread posted on an R/C model forum regarding changing an Electronic Speed Control unit driving a small brushless motor from PWM or PPM to I2c control. The hardware and software loading is not proving to problematic but I would like to have a small program to test the finished control unit and am not familiar at all with I2c commands. I have tried to find an example program to point me in the right direction but without success.
If possible I would like to simply ramp the finished controller to max speed, hold for a time period and then ramp down again. I know the address of the motor and how to connect it to the Arduino but do not know how to construct the code.
All suggestions appreciated!
Regards
David
So what I2C device is it and how is it wired to the arduino?
Without that you can't begin to write any code.
Yes, you need to know what you need first before doing anything...
Hi,
The device I want to control is the modified Electronic Speed Control unit. This normally takes a PWM signal from a radio control unit to control the speed of a 3 phase brushless motor connected to its output. Power to the ESC is provided by a 3S LiPo battery. The modified unit is recoded to accept an I2c command to set the required speed. I understood that the Arduino provided I2c from Analog pin 4 (SDA) and Analog pin 5 (SCL). This is about as far as my current knowledge will take me! All help gratefully received.
Thanks
David
Sorry that is no where near enough information to even begin to help you.
You need to know what device you have, what register structure it has and how it is wired up.
The phrase the modified Electronic Speed Control unit is not enough to identify it.
Hi Mike,
Thanks - I'll dig a little deeper and see what I can come up with.
David
Hello!
Why don´t you just use the same ppm signal as for a servo??
Best regards
Hi, is this the controller in question?
Tower hobbies?
Then you are trying to interface to ATMega8 from AMTEL
the modifying is connecting extra wires to SMT mounted chip (the SDA and SCL + common ground et cetera...)
there is a zip file on this webpage with hex file
I do not want to figure out the TWI/I2C protocol as I have never had to use it in my projects yet, but I think eventually I must do it as I plan to use LCD screen soon...
EDIT: found some protocol pages:
http://forum.mikrokopter.com/topic-923.html
David
Those suckers would make mean PID opto-encoded CNC machine motorcontrollers
They are able to handle 12 volts at 20A !!!
THe purpose of the conversion is to get a faster response, or 300 pulses/sec stable, wich the ppm signal is not able to do (at least not in a relativly unexpensive package as this). Usually the max pulse rate is about 150 pulses/sec so this hack gives better speed/response.
David
Hi ArduinoM,
The web link you posted is the correct one. I've no problem doing the hardware mods but I do not want to control it from one of the microcopter boards, I have something else in mind. The hex files don't help me. What I need to do is get a basic understanding of how the I2c code is structured so I can write a simple test program to check the unit after modification. On the same site somebody has posted a visual basic program for testing the ESC but I have just started to experiment with the Arduino and thought it would be ideal - however I am starting to think I am out of my depth!!!
I may just build the circuit shown for use with visual basic program and see where that takes me. Doesn't help me understand I2c though.
Thanks for taking the time to respond to my post.
David
I have not actually used I2C, yet as my project have not required it
BUT, and that is a big but it is probably not hard to learn as so many things use it and there are TUTORIALS on the net. So just pack for a INFOQUEST ;D and start googling tutorials for I2C.
here is a starting point:
http://www.arduino.cc/playground/Learning/I2C
http://combustory.com/wiki/index.php/X9241A_-_Digital_Potentiometer
I would definetly use those controllers for somthing completly different also
It is just sending and receving the commands (it's kinda like serial) using the hex codes that you saw on the linked site to the Microkopters so you send the hex commands followed by your parameters that the command can take. Should be easy-peasy (especially using those ready made libraries such as wiring.h )
The visual basic program is doing just the same thing, dont be afraid to experiment with the arduino, dive head in to the deep end as you probably learn most there
I am going to do i2c projet at the end of the summer, as I am pretty swamped right now with work, but I do a little bit of research now and then for my next idea, there is always a next idea but so little time.
Start to write a skeleton code from tutorials and tweek to your needs. Post for help when you really are stuck, nobody likes to write a whole program for you, but very many people like to tinker with sombody's else code
David
Hi David
I think your advise is good. The tutorials are a help and I had already started to look around for more info. My post on here wasn't meant to come over as being lazy, I really want to learn for myself but sometimes a pointer in the right direction saves a great deal of time.
Once again thanks for the help and I'll drop you a line if I manage to sort something out.
Cheers
What are you gonna make?
Never crossed my mind that you were beeing lazy, I would not have answered your post then
It is always best to get a kickstart from someone experienced, but I am not the one to ask about I2C, as I don't have I2c device to connect to my Mega (would wish i had though).
Although I am intressed in those things and I am compiling info and is glad to share them. Have 1-RC-Plane with .35 motor (fuel) and 1 Electric RC plane and RC-car (fuel).
I am planning to use I2C LCD panel in one of my project, but that can wait a bit (octane number of the gasoline in my car project, will do it after the summer).
I am starting to assemble a small Arduino-CNC now. Steppers and all materials are bought, just need to find the time :-[
David
Hi David,
I also fly RC stuff although more helicopter based than Planes. Its a bad habit to get - already cost me a small fortune over the years! Just graduated to a 90 size Henseleit 3DNT heli last year. This interest actually stemmed from something I want to do at work. I realised that I could use a Hacker outrunner motor to drive one of my small laboratory machines and made a temp rig to test out the mechanics using a servo tester. Worked very well and the motor proved up to the job but I'm not happy with the method of control and wanted to increase response speed as well as being able to address the motor using the data bus.
Still working on it though!! I noticed yesterday that someone else (with more experience than I) had had the same thought about using an Arduino to test the modified ESC so I hope he will post the code at some point.
Cheers for the help anyway
D
Hi again, Have you seen the Aeroquad arduino code
from the looks of it it is a mix of german and italian coding ;D
try to disect it:
/*
AeroQuad v1.5 - Novmeber 2009
www.AeroQuad.info
Copyright (c) 2009 Ted Carancho. All rights reserved.
An Open Source Arduino based quadrocopter.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Motors.h"
// I2C Konstanten
#define SCL_CLOCK 200000L
#define I2C_TIMEOUT 30000
#define I2C_START 0x08
#define I2C_REPEATED_START 0x10
#define I2C_TX_SLA_ACK 0x18
#define I2C_TX_DATA_ACK 0x28
#define I2C_RX_SLA_ACK 0x40
#define I2C_RX_DATA_ACK 0x50
#define MAX_MOTORS 6
#define CPU_FREQ 16000000L
#define TWI_FREQ 200000L
#define RFRONT 5
#define RREAR 0
#define RLEFT 2
#define RRIGHT 3
//############################################################################
//#include <Wire.h>
volatile unsigned char twi_state = 0;
unsigned char Motor[MAX_MOTORS];
unsigned char i2cmotor=0,PlatinenVersion=0;
unsigned char motors=0;
unsigned char motorread = 0,MissingMotor = 0;
unsigned char motor_rx[16],motor_rx2[16];
unsigned char MotorPresent[MAX_MOTORS];
unsigned char MotorError[MAX_MOTORS];
unsigned int I2CTimeout=100;
unsigned int I2CError = 0;
struct
{
char Revision;
char Name[12];
signed char Motor[16][4];
} Mixer;
byte x = 0;
int mnumber = 6;
byte command=0;
//############################################################################
//Initzialisieren der I2C (TWI) Schnittstelle
void i2c_init(void)
//############################################################################
{
TWSR = 0;
//TWBR = ((CPU_FREQ/TWI_FREQ)-16)/2;
TWBR = ((CPU_FREQ/TWI_FREQ)-16)/2;
TWBR = 0x15;
}
//############################################################################
//Start I2C
void i2c_start(void)
//############################################################################
{
TWCR = (1<<TWSTA) | (1<<TWEN) | (1<<TWINT) | (1<<TWIE);
}
//############################################################################
void i2c_stop(void)
//############################################################################
{
TWCR = (1<<TWEN) | (1<<TWSTO) | (1<<TWINT);
}
void i2c_reset(void)
//############################################################################
{
i2c_stop();
twi_state = 0;
i2cmotor = TWDR;
i2cmotor = 0;
TWCR = 0x80;
TWAMR = 0;
TWAR = 0;
TWDR = 0;
TWSR = 0;
TWBR = 0;
i2c_init();
i2c_start();
i2c_write_byte(0);
}
//############################################################################
void i2c_write_byte(char i2cbyte)
//############################################################################
{
TWSR = 0x00;
TWDR = i2cbyte;
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWIE);
}
/****************************************/
/* Write to I2C */
/****************************************/
void I2C_WriteByte(int8_t i2cbyte)
{
// move byte to send into TWI Data Register
TWDR = i2cbyte;
// clear interrupt flag (TWINT = 1)
// enable i2c bus (TWEN = 1)
// enable interrupt (TWIE = 1)
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWIE);
}
/****************************************/
/* Receive byte and send ACK */
/****************************************/
void I2C_ReceiveByte(void)
{
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWIE) | (1<<TWEA);
}
/****************************************/
/* I2C receive last byte and send no ACK*/
/****************************************/
void I2C_ReceiveLastByte(void)
{
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWIE);
}
//############################################################################
SIGNAL (TWI_vect)
//############################################################################
{
static unsigned char missing_motor;
static unsigned char nmotor;
//Serial.print("TWI_VECT");
switch(twi_state++)
{
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Writing the Data
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
case 0: //i2cmotor++; // skip if not used
switch(i2cmotor)
{
case 0:
nmotor=RFRONT;
break;
case 1:
nmotor=RREAR;
break;
case 2:
nmotor=RRIGHT;
break;
case 3:
nmotor=RLEFT;
break;
default:;
}
i2c_write_byte(0x52+((nmotor)*2));
//Serial.print("I2C ADDR");
//Serial.print(i2cmotor);
//Serial.println("");
break;
case 1:
switch(i2cmotor++)
{
case 0:
i2c_write_byte(Motor[FRONTMOTORID]);
break;
case 1:
i2c_write_byte(Motor[REARMOTORID]);
break;
case 2:
i2c_write_byte(Motor[RIGHTMOTORID]);
break;
case 3:
i2c_write_byte(Motor[LEFTMOTORID]);
break;
default:
break;
}
//Serial.print("I2C PWR LEVEL");
//Serial.print(Motor[i2cmotor]);
//Serial.println();
break;
case 2:
// if(TWSR == 0x30)
// {
// if(!missing_motor) missing_motor = i2cmotor;
// if(++MotorError[i2cmotor-1] == 0) MotorError[i2cmotor-1] = 255;
// }
i2c_stop();
//Serial.println("I2C STOP");
if (i2cmotor<4)
{
twi_state=0;
i2c_start();
}
else
{
motor=0;
}
//I2CTimeout = 10;
//i2c_start();
break;
code will continue in next post (it will be on page 2)(see down left)
David
cont from above:
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Reading Data
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
/*
case 3:
//Transmit 1st byte for reading
if(TWSR != 0x40) // Error?
{
MotorPresent[motorread] = 0;
motorread++;
if(motorread >= MAX_MOTORS) motorread = 0;
i2c_stop();
twi_state = 0;
}
else
{
MotorPresent[motorread] = ('1' - '-') + motorread;
I2C_ReceiveByte();
}
MissingMotor = missing_motor;
missing_motor = 0;
break;
case 4: //Read 1st byte and transmit 2nd Byte
motor_rx[motorread] = TWDR;
I2C_ReceiveLastByte(); //nack
break;
case 5:
//Read 2nd byte
motor_rx2[motorread++] = TWDR;
if(motorread >= MAX_MOTORS) motorread = 0;
i2c_stop();
twi_state = 0;
break;
*/
default:
twi_state = 0;
break;
}
TWCR |= 0x80;
}
void I2cMotorWrite()
{
twi_state = 0; // Azzero stato di comunicazione con i motori
i2cmotor=0;
i2c_start(); // Do' il via all'informazione verso il motore dopo che ho ricevuto info x tutti e 4.
}
/* ------------------------------ Vecchio software -----------------------------------------------------------*/
void configureMotors() {
#ifdef ServoControl
frontMotor.attach(FRONTMOTORPIN);
rearMotor.attach(REARMOTORPIN);
rightMotor.attach(RIGHTMOTORPIN);
leftMotor.attach(LEFTMOTORPIN);
#endif
#ifdef AnalogWrite
// analogWrite(FRONTMOTORPIN, 124);
// analogWrite(REARMOTORPIN, 124);
// analogWrite(RIGHTMOTORPIN, 124);
// analogWrite(LEFTMOTORPIN, 124);
#endif
#ifdef I2CWrite
unsigned int timer,i,timer2 = 0;
// DDRB = 0x00;
// PORTB = 0x00;
/*
for(timer = 0; timer < 1000; timer++);
if(PINB & 0x01)
{
if(PINB & 0x02) PlatinenVersion = 13;
else PlatinenVersion = 11;
}
else
{
if(PINB & 0x02) PlatinenVersion = 20;
else PlatinenVersion = 10;
}
// In realta' questo e' l'init della scheda
*/
// DDRC = 0x81; // SCL
// DDRC |=0x40; // HEF4017 Reset
// PORTC = 0xff; // Pullup SDA
// DDRB = 0x1B; // LEDs und Druckoffset
// PORTB = 0x01; // LED_Rot
// DDRD = 0x3E; // Speaker & TXD & J3 J4 J5
// PORTD = 0x47; // LED
// MCUSR &=~(1<<WDRF);
// WDTCSR |= (1<<WDCE)|(1<<WDE);
// WDTCSR = 0;
// PORTD=0;
//Serial.print("Configurazioni motori I2C");
//i2c_reset();
i2c_init();
//sei();
i2cmotor=0;
//Serial.print("Spengo i motori");
/*
for(mnumber=1;mnumber<7;mnumber++)
{
I2cMotorWrite(mnumber,0);
Motor[mnumber]=0;
delay(20);
}
*/
#endif
}
void commandMotors() {
#ifdef ServoControl
//frontMotor.write(motorCommand[FRONT]);
//rearMotor.write(motorCommand[REAR]);
//rightMotor.write(motorCommand[RIGHT]);
//leftMotor.write(motorCommand[LEFT]);
#endif
#ifdef AnalogWrite
//analogWrite(FRONTMOTORPIN, (motorCommand[FRONT] * mMotorCommand) + bMotorCommand);
//analogWrite(REARMOTORPIN, (motorCommand[REAR] * mMotorCommand) + bMotorCommand);
//analogWrite(RIGHTMOTORPIN, (motorCommand[RIGHT] * mMotorCommand) + bMotorCommand);
//analogWrite(LEFTMOTORPIN, (motorCommand[LEFT] * mMotorCommand) + bMotorCommand);
#endif
#ifdef I2CWrite
Motor[FRONTMOTORID]=(motorCommand[FRONT] * mMotorCommand) + bMotorCommand; // Setto la potenza in uscita per il motore selezionato
Motor[REARMOTORID]=(motorCommand[REAR] * mMotorCommand) + bMotorCommand; // Setto la potenza in uscita per il motore selezionato
Motor[RIGHTMOTORID]=(motorCommand[RIGHT] * mMotorCommand) + bMotorCommand; // Setto la potenza in uscita per il motore selezionato
Motor[LEFTMOTORID]=(motorCommand[LEFT] * mMotorCommand) + bMotorCommand; // Setto la potenza in uscita per il motore selezionato
I2cMotorWrite();
/*
Serial.print((motorCommand[FRONT] * mMotorCommand) + bMotorCommand);
Serial.print(":");
Serial.print((motorCommand[REAR] * mMotorCommand) + bMotorCommand);
Serial.print(":");
Serial.print((motorCommand[RIGHT] * mMotorCommand) + bMotorCommand);
Serial.print(":");
Serial.print((motorCommand[LEFT] * mMotorCommand) + bMotorCommand);
Serial.println();
*/
#endif
}
// Sends commands to all motors
void commandAllMotors(int motorCommand) {
#ifdef ServoControl
frontMotor.write(motorCommand);
rearMotor.write(motorCommand);
rightMotor.write(motorCommand);
leftMotor.write(motorCommand);
#endif
#ifdef AnalogWrite
//analogWrite(FRONTMOTORPIN, (motorCommand * mMotorCommand) + bMotorCommand);
//analogWrite(REARMOTORPIN, (motorCommand * mMotorCommand) + bMotorCommand);
//analogWrite(RIGHTMOTORPIN, (motorCommand * mMotorCommand) + bMotorCommand);
//analogWrite(LEFTMOTORPIN, (motorCommand * mMotorCommand) + bMotorCommand);
#endif
#ifdef I2CWrite
Motor[FRONTMOTORID]=(motorCommand * mMotorCommand) + bMotorCommand; // Setto la potenza in uscita per il motore selezionato
Motor[REARMOTORID]=(motorCommand * mMotorCommand) + bMotorCommand; // Setto la potenza in uscita per il motore selezionato
Motor[RIGHTMOTORID]=(motorCommand * mMotorCommand) + bMotorCommand; // Setto la potenza in uscita per il motore selezionato
Motor[LEFTMOTORID]=(motorCommand * mMotorCommand) + bMotorCommand; // Setto la potenza in uscita per il motore selezionato
I2cMotorWrite();
#endif
}
void pulseMotors(byte quantity) {
for (byte i = 0; i < quantity; i++) {
commandAllMotors(MINCOMMAND + 100);
delay(250);
commandAllMotors(MINCOMMAND);
delay(250);
}
}
The link to the code is:
http://code.google.com/p/lnmultipilot10/source/browse/trunk/Application/AeroQuad/Motors.pde
Look to the right side and click on "View Raw File" this is the motors.pde sketch
Comments in italian or german can be made humanly readable with:
just paste the comments in and translate from either italian or german
Cheers and hope you can make any sense of it
David
EDIT:
Actually its better to view all the files: AeroQuad.pde is the main file that brings them all together:
http://code.google.com/p/lnmultipilot10/source/browse/trunk/Application/AeroQuad/
Hi David,
This is perfect for what I want to do. I think I can use this to get a bare bones code to test a single motor. Looks like some late nights are coming up!
Thanks for all the help. Actually the quadkopter thing looks interesting too... may take a diversion from standard helicopters for a while.
Cheers
D