Lạm bàn thêm về tí RC brushless ESC chút nhé bác chủ.. vì nó cũng thuộc nhóm BLDC/BLAC.
Như sơ đồ trên thì việc điều khiển PWM nếu có thề chỉ có thể điều khiển theo squence, hoặc một phần từ back EMF. Không chính xác thì không đo được dòng phản hồi trên coil.
Xem thêm http://dronespersonalizados.blogspot...13/11/esc.html
Vấn đề RC brushless thì không còn mới.. do đó có rất nhiều thông tin liên quan có thể tìm từ google.com. Qua đó có thể dẽ dàng hiểu được nguyên lý vận hành của mấy chú BLDC. Nếu kết hợp với sensor, kết hợp PWM, mô phỏng sin, điều khiển chính xác tốc độ, chiều quay, gia tốc lớn thì việc biến nó thành servo thiết nghĩ không khó. Thêm mấy cái PID, PI, PD.. hay PIV gì đó là được.
Vụ này bác Gamo nghiên cứu từ từ nhé. Em thì mới theo học môn này.. nên em quay lại điều khiển RC servo cho lành hehe. Mấy cái vụ DC servo, BLDC servo, BLAC servo gì đó.. em xin khất.. chạy theo cho có tụ vậy thôi
Bổ xung thêm Code for atmage328 theo sơ đồ trên.
Mã:#include <avr/io.h> #include <util/delay.h> #include <stdio.h> #define TPC_PIN_INPUT() DDRD &= ~_BV(6) #define TPC_PIN_OUTPUT() DDRD |= _BV(6) #define TPC_PIN_ON() PORTD |= _BV(6) #define TPC_PIN_OFF() PORTD &= ~_BV(6) #define TPC_PIN_IS_ON() bit_is_set(PIND, 6) #define TPC_PIN_IS_OFF() bit_is_clear(PIND, 6) #define TPC_delay_us(x) _delay_us(x) #define TPC_READ_BIT_TIME_WIDTH 2437 #define TPC_READ_HALF_BIT_TIME_WIDTH (TPC_READ_BIT_TIME_WIDTH/2) #define TPC_WRITE_BIT_TIME_WIDTH TPC_READ_BIT_TIME_WIDTH #define TPC_WRITE_HALF_BIT_TIME_WIDTH (TPC_WRITE_BIT_TIME_WIDTH/2) enum TPC_battType_t { TPC_battType_Li = 0, TPC_battType_Ni = 1 }; enum TPC_cutoffType_t { TPC_cutoffType_softCut = 0, TPC_cutoffType_cutoff = 1 }; enum TPC_cutoffVoltage_t { TPC_cutoffVoltage_low = 0, TPC_cutoffVoltage_middle = 1, TPC_cutoffVoltage_high = 2 }; enum TPC_startMode_t { TPC_startMode_normal = 0, TPC_startMode_soft = 1, TPC_startMode_verySoft = 2 }; enum TPC_timingMode_t { TPC_timingMode_low = 0, TPC_timingMode_middle = 1, TPC_timingMode_high = 2 }; enum TPC_lipoCells_t { TPC_lipoCells_autoDetect = 0, TPC_lipoCells_2 = 1, TPC_lipoCells_3 = 2, TPC_lipoCells_4 = 3, TPC_lipoCells_5 = 4, TPC_lipoCells_6 = 5, TPC_lipoCells_7 = 6, TPC_lipoCells_8 = 7, TPC_lipoCells_9 = 8, TPC_lipoCells_10 = 9, TPC_lipoCells_11 = 10, TPC_lipoCells_12 = 11 }; typedef struct TPC_settings_t_ { char brake; enum TPC_battType_t battType; enum TPC_cutoffType_t cutoffType; enum TPC_cutoffVoltage_t cutoffVoltage; enum TPC_startMode_t startMode; enum TPC_timingMode_t timingMode; enum TPC_lipoCells_t lipoCells; char governorMode; } TPC_settings_t; // initializes the settings to default values void TPC_loadDefault(TPC_settings_t* x) { x->brake = 0; x->battType = TPC_battType_Li; x->cutoffType = TPC_cutoffType_softCut; x->cutoffVoltage = TPC_cutoffVoltage_middle; x->startMode = TPC_startMode_normal; x->timingMode = TPC_timingMode_low; x->lipoCells = TPC_lipoCells_autoDetect; x->governorMode = 0; } // configs the settings struct with 2 bytes (which you should get from the ESC, but you can also store it in your own EEPROM or something) void TPC_word_to_struct(TPC_settings_t* x, unsigned short y) { // map the bits to the settings x->brake = (y & (1 << 0)) == 0 ? 0 : 1; x->battType = (y & (1 << 1)) == 0 ? TPC_battType_Li : TPC_battType_Ni; x->cutoffType = (y & (1 << 2)) == 0 ? TPC_cutoffType_softCut : TPC_cutoffType_cutoff; x->cutoffVoltage = ((y & (0x03 << 3)) >> 3); x->startMode = ((y & (0x03 << 5)) >> 5); x->timingMode = ((y & (0x03 << 8)) >> 8); x->lipoCells = ((y & (0x0F << 10)) >> 10); x->governorMode = (y & (1 << 7)) == 0 ? 0 : 1; } // translates the settings struct into 2 bytes (which you can send to the ESC, or store in your own EEPROM or something) unsigned short TPC_struct_to_word(TPC_settings_t* x) { return 0 | ((x->brake ? 1 : 0) << 0) | ((x->battType ? 1 : 0) << 1) | ((x->cutoffType ? 1 : 0) << 2) | ((x->cutoffVoltage & 0x03) << 3) | ((x->startMode & 0x03) << 5) | ((x->timingMode & 0x03) << 8) | ((x->lipoCells & 0x0F) << 10) | ((x->governorMode ? 1 : 0) << 7); } // reads a byte from a psuedo 10-bit UART unsigned char TPC_ser_read() { unsigned char i, x = 0; TPC_PIN_ON(); // input TPC_PIN_INPUT(); while (TPC_PIN_IS_OFF()); // wait for powerup if not already while (TPC_PIN_IS_ON()); // wait until start of frame while (TPC_PIN_IS_OFF()); // this period indicates start of frame while (TPC_PIN_IS_ON()); // the first bit always seems to be 1 TPC_delay_us(TPC_READ_BIT_TIME_WIDTH + TPC_READ_HALF_BIT_TIME_WIDTH); // skip // read the 8 bits LSB first for (i = 0; i < 8; i++) { x |= (TPC_PIN_IS_ON() ? 1 : 0) << i; TPC_delay_us(TPC_READ_BIT_TIME_WIDTH); } return x; } // writes a byte to a psuedo 10-bit UART void TPC_ser_write(unsigned char x) { TPC_PIN_ON(); // make sure TPC_PIN_OUTPUT(); TPC_delay_us(TPC_WRITE_BIT_TIME_WIDTH); TPC_PIN_OFF(); // signal start TPC_delay_us(TPC_WRITE_BIT_TIME_WIDTH); TPC_PIN_ON(); // first bit always 1 TPC_delay_us(TPC_WRITE_BIT_TIME_WIDTH); TPC_PIN_OFF(); // 2nd bit always 0 TPC_delay_us(TPC_WRITE_BIT_TIME_WIDTH); // send the byte LSB first char i; for (i = 0; i < 8; i++) { if ((x & (1 << i)) == 0) { TPC_PIN_OFF(); } else { TPC_PIN_ON(); } TPC_delay_us(TPC_WRITE_BIT_TIME_WIDTH); } TPC_PIN_ON(); // leave as input TPC_PIN_INPUT(); } // must be sent after receiving configuration from ESC upon initialization void TPC_send_init_ack() { TPC_PIN_ON(); TPC_PIN_OUTPUT(); TPC_delay_us(TPC_WRITE_BIT_TIME_WIDTH); // send pulses char i; for (i = 0; i < 6; i++) { TPC_PIN_OFF(); TPC_delay_us(TPC_WRITE_BIT_TIME_WIDTH); TPC_PIN_ON(); TPC_delay_us(TPC_WRITE_BIT_TIME_WIDTH); } TPC_PIN_INPUT(); // leave clean } // receive the ack from ESC after writing config to ESC void TPC_wait_for_ack() { TPC_ser_read(); } // receive current config from ESC void TPC_read_init(TPC_settings_t* x) { // read in 2 bytes unsigned short y; y = TPC_ser_read(); y |= TPC_ser_read() << 8; TPC_word_to_struct(x, y); TPC_delay_us(TPC_READ_BIT_TIME_WIDTH); // a small delay TPC_delay_us(TPC_READ_BIT_TIME_WIDTH); // a small delay TPC_delay_us(TPC_READ_BIT_TIME_WIDTH); // a small delay TPC_delay_us(TPC_READ_BIT_TIME_WIDTH); // a small delay TPC_send_init_ack(); // must be sent after receiving configuration from ESC upon initialization } // sends configuration to ESC void TPC_send_config(TPC_settings_t* x) { unsigned short y = TPC_struct_to_word(x); // start writing the config, LSB first TPC_ser_write(y & 0xFF); TPC_ser_write((y >> 8) & 0xFF); // just a small note, these two bytes match the received config during initialization // the settings are sent in this format TPC_ser_write((y & (0x01 << 0)) >> 0); TPC_ser_write((y & (0x01 << 1)) >> 1); TPC_ser_write((y & (0x01 << 2)) >> 2); TPC_ser_write((y & (0x03 << 3)) >> 3); TPC_ser_write((y & (0x03 << 5)) >> 5); TPC_ser_write((y & (0x03 << 8)) >> 8); TPC_ser_write((y & (0x01 << 7)) >> 7); // this is where the string of notes would be, but I don't have that implemented, so these two are just null TPC_ser_write(0); TPC_ser_write(0); TPC_ser_write(11); // this is actually a byte count TPC_wait_for_ack(); // do not unpower ESCs until the ack has been received, since it's writing to EEPROM during this time } static int ser_tx(char c, FILE* f) { loop_until_bit_is_set(UCSR0A, UDRE0); UDR0 = c; return 0; } static FILE mystdout = FDEV_SETUP_STREAM(ser_tx, NULL, _FDEV_SETUP_WRITE); int main() { // setup for 57600 baud UBRR0H = 0; UBRR0L = 12; UCSR0B = _BV(TXEN0) | _BV(RXEN0); // start serial port stdout = &mystdout; // setup stream DDRD |= _BV(4); // LED pin output TPC_PIN_ON(); TPC_PIN_INPUT(); printf("\r\nTesting Begin\r\n"); // at this point, plug in the ESC to the battery static volatile TPC_settings_t mySettings; PORTD |= _BV(4); // LED on TPC_read_init(&mySettings); PORTD &= ~_BV(4); // LED off unsigned short x = TPC_struct_to_word(&mySettings); printf("Read from ESC: 0x%x\r\n", x); // here we change all the settings mySettings.brake = mySettings.brake ? 0 : 1; mySettings.battType = mySettings.battType ? 0 : 1; mySettings.cutoffType = mySettings.cutoffType ? 0 : 1; mySettings.cutoffVoltage = (mySettings.cutoffVoltage + 1) % 3; mySettings.startMode = (mySettings.startMode + 1) % 3; mySettings.timingMode = (mySettings.timingMode + 1) % 3; mySettings.lipoCells = (mySettings.lipoCells + 1) % (TPC_lipoCells_12 + 1); mySettings.governorMode = mySettings.governorMode ? 0 : 1; x = TPC_struct_to_word(&mySettings); printf("Sending to ESC: 0x%x\r\n", x); // and send it back _delay_ms(1000); PORTD |= _BV(4); // LED on TPC_send_config(&mySettings); PORTD &= ~_BV(4); // LED off printf("Test Complete\r\n"); // now the ESC must be unpowered // then reset the system // to confirm settings while (1); return 0; }



để chia sẻ bài viết lên facebook


.
Trả lời kèm Trích dẫn
