Moussa Oudjama
/
XBEE_RECEIVER_V3
Version 3 pour le majeur et l'index
PCA9685.cpp@0:72bac9981dc5, 2018-06-21 (annotated)
- Committer:
- MoussOudj
- Date:
- Thu Jun 21 16:29:18 2018 +0000
- Revision:
- 0:72bac9981dc5
XBEE_RECEIVER_V3
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
MoussOudj | 0:72bac9981dc5 | 1 | #ifndef PCA9685_LIBRARY_CPP |
MoussOudj | 0:72bac9981dc5 | 2 | #define PCA9685_LIBRARY_CPP |
MoussOudj | 0:72bac9981dc5 | 3 | |
MoussOudj | 0:72bac9981dc5 | 4 | |
MoussOudj | 0:72bac9981dc5 | 5 | #include "mbed.h" |
MoussOudj | 0:72bac9981dc5 | 6 | #include "PCA9685.h" |
MoussOudj | 0:72bac9981dc5 | 7 | #include "definitions.h" |
MoussOudj | 0:72bac9981dc5 | 8 | |
MoussOudj | 0:72bac9981dc5 | 9 | |
MoussOudj | 0:72bac9981dc5 | 10 | PCA9685::PCA9685(uint8_t i2c_address, I2C i2c_object, float frequency) : |
MoussOudj | 0:72bac9981dc5 | 11 | |
MoussOudj | 0:72bac9981dc5 | 12 | i2c_addr(i2c_address), |
MoussOudj | 0:72bac9981dc5 | 13 | freq(frequency), |
MoussOudj | 0:72bac9981dc5 | 14 | i2c(i2c_object) |
MoussOudj | 0:72bac9981dc5 | 15 | |
MoussOudj | 0:72bac9981dc5 | 16 | { |
MoussOudj | 0:72bac9981dc5 | 17 | |
MoussOudj | 0:72bac9981dc5 | 18 | } |
MoussOudj | 0:72bac9981dc5 | 19 | |
MoussOudj | 0:72bac9981dc5 | 20 | void PCA9685::init(void) |
MoussOudj | 0:72bac9981dc5 | 21 | { |
MoussOudj | 0:72bac9981dc5 | 22 | |
MoussOudj | 0:72bac9981dc5 | 23 | reset(); |
MoussOudj | 0:72bac9981dc5 | 24 | |
MoussOudj | 0:72bac9981dc5 | 25 | uint8_t prescale = (uint8_t) (OSC_CLOCK / (4096 * PWM_SCALER * freq)) - 1; |
MoussOudj | 0:72bac9981dc5 | 26 | |
MoussOudj | 0:72bac9981dc5 | 27 | write_8(MODE1, 0x21); //0010 0001 : AI ENABLED |
MoussOudj | 0:72bac9981dc5 | 28 | write_8(MODE2, 0x07); //0000 0111 : NOT INVRT, CHANGE ON STOP, TOTEM POLE, \OE = 1, LEDn = HIGH IMP |
MoussOudj | 0:72bac9981dc5 | 29 | |
MoussOudj | 0:72bac9981dc5 | 30 | set_prescale(prescale); |
MoussOudj | 0:72bac9981dc5 | 31 | |
MoussOudj | 0:72bac9981dc5 | 32 | } |
MoussOudj | 0:72bac9981dc5 | 33 | |
MoussOudj | 0:72bac9981dc5 | 34 | void PCA9685::reset(void) |
MoussOudj | 0:72bac9981dc5 | 35 | { |
MoussOudj | 0:72bac9981dc5 | 36 | |
MoussOudj | 0:72bac9981dc5 | 37 | write_8(MODE1,0x00); |
MoussOudj | 0:72bac9981dc5 | 38 | |
MoussOudj | 0:72bac9981dc5 | 39 | } |
MoussOudj | 0:72bac9981dc5 | 40 | |
MoussOudj | 0:72bac9981dc5 | 41 | void PCA9685::set_prescale(uint8_t prescale) |
MoussOudj | 0:72bac9981dc5 | 42 | { |
MoussOudj | 0:72bac9981dc5 | 43 | |
MoussOudj | 0:72bac9981dc5 | 44 | uint8_t oldmode = read_8(MODE1); |
MoussOudj | 0:72bac9981dc5 | 45 | uint8_t newmode = (oldmode&0x7F) | 0x10; // set the sleep bit |
MoussOudj | 0:72bac9981dc5 | 46 | |
MoussOudj | 0:72bac9981dc5 | 47 | write_8(MODE1, newmode); // send the device to sleep |
MoussOudj | 0:72bac9981dc5 | 48 | wait_ms(5); |
MoussOudj | 0:72bac9981dc5 | 49 | write_8(PRESCALE, prescale); // set the prescaler |
MoussOudj | 0:72bac9981dc5 | 50 | write_8(MODE1, oldmode); |
MoussOudj | 0:72bac9981dc5 | 51 | wait_ms(5); |
MoussOudj | 0:72bac9981dc5 | 52 | write_8(MODE1, oldmode | 0xa1); // wake up the device |
MoussOudj | 0:72bac9981dc5 | 53 | |
MoussOudj | 0:72bac9981dc5 | 54 | } |
MoussOudj | 0:72bac9981dc5 | 55 | |
MoussOudj | 0:72bac9981dc5 | 56 | |
MoussOudj | 0:72bac9981dc5 | 57 | //NB REQUIRES AUTO-INCREMENT MODE ENABLED |
MoussOudj | 0:72bac9981dc5 | 58 | //0 <= pwm_output <= 15 |
MoussOudj | 0:72bac9981dc5 | 59 | //0 <= (count_on || count_off) <= 4095 |
MoussOudj | 0:72bac9981dc5 | 60 | void PCA9685::set_pwm_output(int pwm_output, uint16_t count_on, uint16_t count_off) |
MoussOudj | 0:72bac9981dc5 | 61 | { |
MoussOudj | 0:72bac9981dc5 | 62 | |
MoussOudj | 0:72bac9981dc5 | 63 | char msg[5]; |
MoussOudj | 0:72bac9981dc5 | 64 | |
MoussOudj | 0:72bac9981dc5 | 65 | msg[0] = LED0_ON_L + (4 * pwm_output); |
MoussOudj | 0:72bac9981dc5 | 66 | msg[1] = count_on; |
MoussOudj | 0:72bac9981dc5 | 67 | msg[2] = count_on >> 8; |
MoussOudj | 0:72bac9981dc5 | 68 | msg[3] = count_off; |
MoussOudj | 0:72bac9981dc5 | 69 | msg[4] = count_off >> 8; |
MoussOudj | 0:72bac9981dc5 | 70 | |
MoussOudj | 0:72bac9981dc5 | 71 | i2c.write(i2c_addr, msg, 5); |
MoussOudj | 0:72bac9981dc5 | 72 | |
MoussOudj | 0:72bac9981dc5 | 73 | } |
MoussOudj | 0:72bac9981dc5 | 74 | |
MoussOudj | 0:72bac9981dc5 | 75 | void PCA9685::set_pwm_output_on_0(int pwm_output, uint16_t count_off) |
MoussOudj | 0:72bac9981dc5 | 76 | { |
MoussOudj | 0:72bac9981dc5 | 77 | |
MoussOudj | 0:72bac9981dc5 | 78 | char msg[3]; |
MoussOudj | 0:72bac9981dc5 | 79 | |
MoussOudj | 0:72bac9981dc5 | 80 | msg[0] = LED0_ON_L + 2 + (4 * pwm_output); |
MoussOudj | 0:72bac9981dc5 | 81 | msg[1] = count_off; |
MoussOudj | 0:72bac9981dc5 | 82 | msg[2] = count_off >> 8; |
MoussOudj | 0:72bac9981dc5 | 83 | |
MoussOudj | 0:72bac9981dc5 | 84 | i2c.write(i2c_addr,msg,3); |
MoussOudj | 0:72bac9981dc5 | 85 | |
MoussOudj | 0:72bac9981dc5 | 86 | } |
MoussOudj | 0:72bac9981dc5 | 87 | |
MoussOudj | 0:72bac9981dc5 | 88 | |
MoussOudj | 0:72bac9981dc5 | 89 | //NB REQUIRES AUTO-INCREMENT MODE ENABLED |
MoussOudj | 0:72bac9981dc5 | 90 | //0 <= pwm_output <= 15 |
MoussOudj | 0:72bac9981dc5 | 91 | void PCA9685::set_pwm_duty(int pwm_output, float duty_cycle) |
MoussOudj | 0:72bac9981dc5 | 92 | { |
MoussOudj | 0:72bac9981dc5 | 93 | |
MoussOudj | 0:72bac9981dc5 | 94 | if (duty_cycle > 1.0) { |
MoussOudj | 0:72bac9981dc5 | 95 | duty_cycle = 1.0; |
MoussOudj | 0:72bac9981dc5 | 96 | } |
MoussOudj | 0:72bac9981dc5 | 97 | if (duty_cycle < 0.0) { |
MoussOudj | 0:72bac9981dc5 | 98 | duty_cycle = 0.0; |
MoussOudj | 0:72bac9981dc5 | 99 | } |
MoussOudj | 0:72bac9981dc5 | 100 | |
MoussOudj | 0:72bac9981dc5 | 101 | uint16_t count_off = (uint16_t) (duty_cycle * 4095); |
MoussOudj | 0:72bac9981dc5 | 102 | uint16_t count_on = 0x0000; |
MoussOudj | 0:72bac9981dc5 | 103 | |
MoussOudj | 0:72bac9981dc5 | 104 | set_pwm_output(pwm_output, count_on, count_off); |
MoussOudj | 0:72bac9981dc5 | 105 | |
MoussOudj | 0:72bac9981dc5 | 106 | } |
MoussOudj | 0:72bac9981dc5 | 107 | |
MoussOudj | 0:72bac9981dc5 | 108 | |
MoussOudj | 0:72bac9981dc5 | 109 | //NB REQUIRES AUTO-INCREMENT MODE ENABLED |
MoussOudj | 0:72bac9981dc5 | 110 | //0 <= pwm_output <= 15 |
MoussOudj | 0:72bac9981dc5 | 111 | void PCA9685::set_pwm_pw(int pwm_output, float pulse_width_us) |
MoussOudj | 0:72bac9981dc5 | 112 | { |
MoussOudj | 0:72bac9981dc5 | 113 | |
MoussOudj | 0:72bac9981dc5 | 114 | float period_us = (1e6/freq); |
MoussOudj | 0:72bac9981dc5 | 115 | |
MoussOudj | 0:72bac9981dc5 | 116 | float duty = pulse_width_us/period_us; |
MoussOudj | 0:72bac9981dc5 | 117 | |
MoussOudj | 0:72bac9981dc5 | 118 | set_pwm_duty(pwm_output, duty); |
MoussOudj | 0:72bac9981dc5 | 119 | |
MoussOudj | 0:72bac9981dc5 | 120 | } |
MoussOudj | 0:72bac9981dc5 | 121 | |
MoussOudj | 0:72bac9981dc5 | 122 | |
MoussOudj | 0:72bac9981dc5 | 123 | void PCA9685::update(void) |
MoussOudj | 0:72bac9981dc5 | 124 | { |
MoussOudj | 0:72bac9981dc5 | 125 | |
MoussOudj | 0:72bac9981dc5 | 126 | i2c.stop(); |
MoussOudj | 0:72bac9981dc5 | 127 | |
MoussOudj | 0:72bac9981dc5 | 128 | } |
MoussOudj | 0:72bac9981dc5 | 129 | |
MoussOudj | 0:72bac9981dc5 | 130 | |
MoussOudj | 0:72bac9981dc5 | 131 | |
MoussOudj | 0:72bac9981dc5 | 132 | void PCA9685::write_8(uint8_t reg, uint8_t msg) |
MoussOudj | 0:72bac9981dc5 | 133 | { |
MoussOudj | 0:72bac9981dc5 | 134 | |
MoussOudj | 0:72bac9981dc5 | 135 | char send[2]; //Store the address and data in an array |
MoussOudj | 0:72bac9981dc5 | 136 | send[0] = reg; |
MoussOudj | 0:72bac9981dc5 | 137 | send[1] = msg; |
MoussOudj | 0:72bac9981dc5 | 138 | i2c.write(i2c_addr, send, 2); |
MoussOudj | 0:72bac9981dc5 | 139 | |
MoussOudj | 0:72bac9981dc5 | 140 | } |
MoussOudj | 0:72bac9981dc5 | 141 | |
MoussOudj | 0:72bac9981dc5 | 142 | uint8_t PCA9685::read_8(uint8_t reg) |
MoussOudj | 0:72bac9981dc5 | 143 | { |
MoussOudj | 0:72bac9981dc5 | 144 | |
MoussOudj | 0:72bac9981dc5 | 145 | char send[1] ; |
MoussOudj | 0:72bac9981dc5 | 146 | send[0] = reg; |
MoussOudj | 0:72bac9981dc5 | 147 | i2c.write(i2c_addr, send, 1); |
MoussOudj | 0:72bac9981dc5 | 148 | char recieve[1]; |
MoussOudj | 0:72bac9981dc5 | 149 | i2c.read(i2c_addr, recieve, 1); |
MoussOudj | 0:72bac9981dc5 | 150 | return recieve[0]; |
MoussOudj | 0:72bac9981dc5 | 151 | |
MoussOudj | 0:72bac9981dc5 | 152 | } |
MoussOudj | 0:72bac9981dc5 | 153 | |
MoussOudj | 0:72bac9981dc5 | 154 | int PCA9685::convert_pwm_value(float pulse_width_us, float period_us) |
MoussOudj | 0:72bac9981dc5 | 155 | { |
MoussOudj | 0:72bac9981dc5 | 156 | |
MoussOudj | 0:72bac9981dc5 | 157 | int result; |
MoussOudj | 0:72bac9981dc5 | 158 | float interim; |
MoussOudj | 0:72bac9981dc5 | 159 | |
MoussOudj | 0:72bac9981dc5 | 160 | interim = ((pulse_width_us / period_us) * 4095); //scale the pulse width to a 12-bit scale |
MoussOudj | 0:72bac9981dc5 | 161 | result = (int) interim; //round the value to the nearest integer |
MoussOudj | 0:72bac9981dc5 | 162 | |
MoussOudj | 0:72bac9981dc5 | 163 | return result; |
MoussOudj | 0:72bac9981dc5 | 164 | |
MoussOudj | 0:72bac9981dc5 | 165 | } |
MoussOudj | 0:72bac9981dc5 | 166 | |
MoussOudj | 0:72bac9981dc5 | 167 | #endif |