A simple I2C library for ESCs using the Blue Robotics version of SimonK's TGY firmware (https://github.com/bluerobotics/tgy). This library supports the BlueESC, but also the Afro Nfet 30A. I2C is an alternative interface for micro-controllers, rather than using PWM (as a servo) -- this provides some additional features like temperature level, RPM, etc.
Dependents: SimonK_I2C_ESC_Example
Example program here:
Import programSimonK_I2C_ESC_Example
Simple example for the SimonK_I2C_ESC. Tested on the FRDM K64F.
Additional guidance is provided in the Wiki
SimonK_I2C_ESC.cpp@1:7efb04a9c0dd, 2016-04-01 (annotated)
- Committer:
- azazeal88
- Date:
- Fri Apr 01 06:58:04 2016 +0000
- Revision:
- 1:7efb04a9c0dd
- Parent:
- 0:41ddae212f64
- Child:
- 4:014606ea57a3
First Commit
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
azazeal88 | 0:41ddae212f64 | 1 | #include "SimonK_I2C_ESC.h" |
azazeal88 | 0:41ddae212f64 | 2 | |
azazeal88 | 0:41ddae212f64 | 3 | namespace { |
azazeal88 | 0:41ddae212f64 | 4 | char _buffer[9]; |
azazeal88 | 0:41ddae212f64 | 5 | } |
azazeal88 | 0:41ddae212f64 | 6 | |
azazeal88 | 0:41ddae212f64 | 7 | SimonK_I2C_ESC::SimonK_I2C_ESC(I2C &i2c, char address, char poleCount) : _i2c(i2c){ |
azazeal88 | 1:7efb04a9c0dd | 8 | _address = address << 1; |
azazeal88 | 0:41ddae212f64 | 9 | _poleCount = poleCount; |
azazeal88 | 0:41ddae212f64 | 10 | // A timer is needed to calculate the RPM. |
azazeal88 | 0:41ddae212f64 | 11 | mbed_rpm_timer.start(); |
azazeal88 | 0:41ddae212f64 | 12 | _rpmTimer = mbed_rpm_timer.read_ms(); |
azazeal88 | 0:41ddae212f64 | 13 | } |
azazeal88 | 0:41ddae212f64 | 14 | |
azazeal88 | 0:41ddae212f64 | 15 | // Read the incoming data buffer from an ESC |
azazeal88 | 0:41ddae212f64 | 16 | void SimonK_I2C_ESC::readBuffer(char buffer[]) { |
azazeal88 | 0:41ddae212f64 | 17 | char readStartAddress = 0x02; |
azazeal88 | 0:41ddae212f64 | 18 | _i2c.write(_address,&readStartAddress,1,false); |
azazeal88 | 0:41ddae212f64 | 19 | _i2c.read(_address,buffer,9); |
azazeal88 | 0:41ddae212f64 | 20 | } |
azazeal88 | 0:41ddae212f64 | 21 | |
azazeal88 | 0:41ddae212f64 | 22 | // Send motor speed command to ESC |
azazeal88 | 0:41ddae212f64 | 23 | void SimonK_I2C_ESC::set(short throttle) { |
azazeal88 | 0:41ddae212f64 | 24 | char throttleData[3]; |
azazeal88 | 0:41ddae212f64 | 25 | throttleData[0] = 0x00; // Throttle Start Address |
azazeal88 | 0:41ddae212f64 | 26 | throttleData[1] = throttle>>8; |
azazeal88 | 0:41ddae212f64 | 27 | throttleData[2] = throttle; |
azazeal88 | 1:7efb04a9c0dd | 28 | _i2c.write(_address, throttleData, 3, false); |
azazeal88 | 0:41ddae212f64 | 29 | } |
azazeal88 | 0:41ddae212f64 | 30 | |
azazeal88 | 0:41ddae212f64 | 31 | // Send motor speed command to ESC |
azazeal88 | 0:41ddae212f64 | 32 | void SimonK_I2C_ESC::setPWM(short pwm) { |
azazeal88 | 0:41ddae212f64 | 33 | set((pwm - 1100) * (32767 - -32767) / (1900 - 1100) + -32767); |
azazeal88 | 0:41ddae212f64 | 34 | } |
azazeal88 | 0:41ddae212f64 | 35 | |
azazeal88 | 0:41ddae212f64 | 36 | void SimonK_I2C_ESC::update() { |
azazeal88 | 0:41ddae212f64 | 37 | _buffer[8] = 0x00; // Reset last byte so we can check for alive |
azazeal88 | 0:41ddae212f64 | 38 | readBuffer(_buffer); |
azazeal88 | 0:41ddae212f64 | 39 | _rpm = (_buffer[0] << 8) | _buffer[1]; |
azazeal88 | 0:41ddae212f64 | 40 | _voltage_raw = (_buffer[2] << 8) | _buffer[3]; |
azazeal88 | 0:41ddae212f64 | 41 | _temp_raw = (_buffer[4] << 8) | _buffer[5]; |
azazeal88 | 0:41ddae212f64 | 42 | _current_raw = (_buffer[6] << 8) | _buffer[7]; |
azazeal88 | 0:41ddae212f64 | 43 | _identifier = _buffer[8]; |
azazeal88 | 0:41ddae212f64 | 44 | _rpm = float(_rpm) / (( mbed_rpm_timer.read_ms() -_rpmTimer)/1000.0f)*60/ float(_poleCount); |
azazeal88 | 0:41ddae212f64 | 45 | _rpmTimer = mbed_rpm_timer.read_ms(); |
azazeal88 | 0:41ddae212f64 | 46 | } |
azazeal88 | 0:41ddae212f64 | 47 | |
azazeal88 | 0:41ddae212f64 | 48 | bool SimonK_I2C_ESC::isAlive() { |
azazeal88 | 0:41ddae212f64 | 49 | return (_identifier == 0xab); |
azazeal88 | 0:41ddae212f64 | 50 | } |
azazeal88 | 0:41ddae212f64 | 51 | |
azazeal88 | 0:41ddae212f64 | 52 | float SimonK_I2C_ESC::voltage() { |
azazeal88 | 0:41ddae212f64 | 53 | return float(_voltage_raw)/65536.0f*5.0f*6.45f; |
azazeal88 | 0:41ddae212f64 | 54 | } |
azazeal88 | 0:41ddae212f64 | 55 | |
azazeal88 | 0:41ddae212f64 | 56 | float SimonK_I2C_ESC::current() { |
azazeal88 | 0:41ddae212f64 | 57 | return (float(_current_raw)-32767)/65535.0f*5.0f*14.706f; |
azazeal88 | 0:41ddae212f64 | 58 | } |
azazeal88 | 0:41ddae212f64 | 59 | |
azazeal88 | 0:41ddae212f64 | 60 | float SimonK_I2C_ESC::temperature() { |
azazeal88 | 0:41ddae212f64 | 61 | // This code was taken from an Adafruit |
azazeal88 | 0:41ddae212f64 | 62 | float resistance = SERIESRESISTOR/(65535/float(_temp_raw)-1); |
azazeal88 | 0:41ddae212f64 | 63 | |
azazeal88 | 0:41ddae212f64 | 64 | float steinhart; |
azazeal88 | 0:41ddae212f64 | 65 | steinhart = resistance / THERMISTORNOMINAL; // (R/Ro) |
azazeal88 | 0:41ddae212f64 | 66 | steinhart = log(steinhart); // ln(R/Ro) |
azazeal88 | 0:41ddae212f64 | 67 | steinhart /= BCOEFFICIENT; // 1/B * ln(R/Ro) |
azazeal88 | 0:41ddae212f64 | 68 | steinhart += float(1.0) / (TEMPERATURENOMINAL + 273.15); // + (1/To) |
azazeal88 | 0:41ddae212f64 | 69 | steinhart = float (1.0) / steinhart; // Invert |
azazeal88 | 0:41ddae212f64 | 70 | steinhart -= float(273.15); // convert to C |
azazeal88 | 0:41ddae212f64 | 71 | |
azazeal88 | 0:41ddae212f64 | 72 | return steinhart; |
azazeal88 | 0:41ddae212f64 | 73 | } |
azazeal88 | 0:41ddae212f64 | 74 | |
azazeal88 | 0:41ddae212f64 | 75 | short SimonK_I2C_ESC::rpm() { |
azazeal88 | 0:41ddae212f64 | 76 | return _rpm; |
azazeal88 | 0:41ddae212f64 | 77 | } |