2014-01-09 06:20:26 -08:00
|
|
|
/*
|
2015-04-11 01:07:36 -07:00
|
|
|
Copyright 2012-2015 Benjamin Vedder benjamin@vedder.se
|
2014-01-09 06:20:26 -08:00
|
|
|
|
|
|
|
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 "ch.h"
|
|
|
|
#include "hal.h"
|
|
|
|
#include "stm32f4xx_conf.h"
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <math.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
#include "main.h"
|
|
|
|
#include "mcpwm.h"
|
|
|
|
#include "ledpwm.h"
|
2014-09-19 18:22:38 -07:00
|
|
|
#include "comm_usb.h"
|
2014-01-09 06:20:26 -08:00
|
|
|
#include "ledpwm.h"
|
|
|
|
#include "terminal.h"
|
2014-04-12 12:59:33 -07:00
|
|
|
#include "hw.h"
|
2014-04-18 15:09:46 -07:00
|
|
|
#include "app.h"
|
2014-07-19 02:41:16 -07:00
|
|
|
#include "packet.h"
|
2014-09-19 18:22:38 -07:00
|
|
|
#include "commands.h"
|
2014-09-20 04:41:18 -07:00
|
|
|
#include "timeout.h"
|
2014-12-06 19:30:25 -08:00
|
|
|
#include "comm_can.h"
|
2014-12-08 15:11:29 -08:00
|
|
|
#include "ws2811.h"
|
|
|
|
#include "led_external.h"
|
2015-04-11 01:07:36 -07:00
|
|
|
#include "encoder.h"
|
2014-01-09 06:20:26 -08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Timers used:
|
|
|
|
* TIM7: servo
|
|
|
|
* TIM1: mcpwm
|
|
|
|
* TIM2: mcpwm
|
2014-12-08 15:11:29 -08:00
|
|
|
* TIM12: mcpwm
|
2014-01-09 06:20:26 -08:00
|
|
|
* TIM8: mcpwm
|
2015-04-11 01:07:36 -07:00
|
|
|
* TIM3: servo_dec/Encoder (HW_R2)
|
|
|
|
* TIM4: WS2811/WS2812 LEDs/Encoder (other HW)
|
2014-12-06 19:30:25 -08:00
|
|
|
*
|
|
|
|
* DMA/stream Device Function
|
|
|
|
* 1, 2 I2C1 Nunchuk, temp on rev 4.5
|
|
|
|
* 1, 7 I2C1 Nunchuk, temp on rev 4.5
|
|
|
|
* 1, 1 UART3 HW_R2
|
|
|
|
* 1, 3 UART3 HW_R2
|
|
|
|
* 2, 2 UART6 Other HW
|
|
|
|
* 2, 7 UART6 Other HW
|
|
|
|
* 2, 4 ADC mcpwm
|
2014-12-20 03:52:38 -08:00
|
|
|
* 1, 0 TIM4 WS2811/WS2812 LEDs CH1 (Ch 1)
|
|
|
|
* 1, 3 TIM4 WS2811/WS2812 LEDs CH2 (Ch 2)
|
2014-12-06 19:30:25 -08:00
|
|
|
*
|
2014-01-09 06:20:26 -08:00
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Notes:
|
|
|
|
*
|
|
|
|
* Disable USB VBUS sensing:
|
|
|
|
* ChibiOS-RT-master/os/hal/platforms/STM32/OTGv1/usb_lld.c
|
|
|
|
*
|
|
|
|
* change
|
|
|
|
* otgp->GCCFG = GCCFG_VBUSASEN | GCCFG_VBUSBSEN | GCCFG_PWRDWN;
|
|
|
|
* to
|
|
|
|
* otgp->GCCFG = GCCFG_NOVBUSSENS | GCCFG_PWRDWN;
|
|
|
|
*
|
2014-02-23 23:41:25 -08:00
|
|
|
* This should be handled automatically with the latest version of
|
|
|
|
* ChibiOS since I have added an option to the makefile.
|
|
|
|
*
|
2014-01-09 06:20:26 -08:00
|
|
|
*/
|
|
|
|
|
|
|
|
// Private variables
|
|
|
|
#define ADC_SAMPLE_MAX_LEN 4000
|
2014-03-15 14:32:00 -07:00
|
|
|
static volatile int16_t curr0_samples[ADC_SAMPLE_MAX_LEN];
|
|
|
|
static volatile int16_t curr1_samples[ADC_SAMPLE_MAX_LEN];
|
|
|
|
static volatile int16_t ph1_samples[ADC_SAMPLE_MAX_LEN];
|
|
|
|
static volatile int16_t ph2_samples[ADC_SAMPLE_MAX_LEN];
|
|
|
|
static volatile int16_t ph3_samples[ADC_SAMPLE_MAX_LEN];
|
|
|
|
static volatile int16_t vzero_samples[ADC_SAMPLE_MAX_LEN];
|
2014-01-09 06:20:26 -08:00
|
|
|
static volatile uint8_t status_samples[ADC_SAMPLE_MAX_LEN];
|
|
|
|
static volatile int16_t curr_fir_samples[ADC_SAMPLE_MAX_LEN];
|
2014-08-05 13:24:13 -07:00
|
|
|
static volatile int16_t f_sw_samples[ADC_SAMPLE_MAX_LEN];
|
2014-01-09 06:20:26 -08:00
|
|
|
|
|
|
|
static volatile int sample_len = 1000;
|
|
|
|
static volatile int sample_int = 1;
|
|
|
|
static volatile int sample_ready = 1;
|
|
|
|
static volatile int sample_now = 0;
|
|
|
|
static volatile int sample_at_start = 0;
|
2014-02-15 14:36:50 -08:00
|
|
|
static volatile int was_start_sample = 0;
|
2014-03-30 05:12:27 -07:00
|
|
|
static volatile int start_comm = 0;
|
2014-01-09 06:20:26 -08:00
|
|
|
static volatile float main_last_adc_duration = 0.0;
|
|
|
|
|
|
|
|
static WORKING_AREA(periodic_thread_wa, 1024);
|
|
|
|
static WORKING_AREA(sample_send_thread_wa, 1024);
|
2014-07-19 02:41:16 -07:00
|
|
|
static WORKING_AREA(timer_thread_wa, 128);
|
2014-01-09 06:20:26 -08:00
|
|
|
|
|
|
|
static Thread *sample_send_tp;
|
|
|
|
|
|
|
|
static msg_t periodic_thread(void *arg) {
|
|
|
|
(void)arg;
|
|
|
|
|
|
|
|
chRegSetThreadName("Main periodic");
|
|
|
|
|
2014-04-12 12:59:33 -07:00
|
|
|
int fault_print = 0;
|
|
|
|
|
2014-01-09 06:20:26 -08:00
|
|
|
for(;;) {
|
|
|
|
if (mcpwm_get_state() == MC_STATE_RUNNING) {
|
|
|
|
ledpwm_set_intensity(LED_GREEN, 1.0);
|
|
|
|
} else {
|
|
|
|
ledpwm_set_intensity(LED_GREEN, 0.2);
|
|
|
|
}
|
|
|
|
|
2014-12-20 03:52:38 -08:00
|
|
|
mc_fault_code fault = mcpwm_get_fault();
|
|
|
|
if (fault != FAULT_CODE_NONE) {
|
2014-04-12 12:59:33 -07:00
|
|
|
if (!fault_print && AUTO_PRINT_FAULTS) {
|
|
|
|
fault_print = 1;
|
2014-10-24 14:04:10 -07:00
|
|
|
commands_printf("%s\n", mcpwm_fault_to_string(mcpwm_get_fault()));
|
2014-04-12 12:59:33 -07:00
|
|
|
}
|
2014-12-20 03:52:38 -08:00
|
|
|
|
|
|
|
for (int i = 0;i < (int)fault;i++) {
|
|
|
|
ledpwm_set_intensity(LED_RED, 1.0);
|
|
|
|
chThdSleepMilliseconds(250);
|
|
|
|
ledpwm_set_intensity(LED_RED, 0.0);
|
|
|
|
chThdSleepMilliseconds(250);
|
|
|
|
}
|
|
|
|
|
|
|
|
chThdSleepMilliseconds(500);
|
2014-01-09 06:20:26 -08:00
|
|
|
} else {
|
|
|
|
ledpwm_set_intensity(LED_RED, 0.0);
|
2014-04-12 12:59:33 -07:00
|
|
|
fault_print = 0;
|
2014-01-09 06:20:26 -08:00
|
|
|
}
|
|
|
|
|
2014-03-13 07:28:56 -07:00
|
|
|
if (mcpwm_get_state() == MC_STATE_DETECTING) {
|
2014-09-19 18:22:38 -07:00
|
|
|
commands_send_rotor_pos(mcpwm_get_detect_pos());
|
2014-03-13 07:28:56 -07:00
|
|
|
}
|
|
|
|
|
2014-03-15 14:32:00 -07:00
|
|
|
chThdSleepMilliseconds(25);
|
2014-01-09 06:20:26 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static msg_t sample_send_thread(void *arg) {
|
|
|
|
(void)arg;
|
|
|
|
|
|
|
|
chRegSetThreadName("Main sample");
|
|
|
|
|
|
|
|
sample_send_tp = chThdSelf();
|
|
|
|
|
|
|
|
for(;;) {
|
|
|
|
chEvtWaitAny((eventmask_t) 1);
|
|
|
|
|
|
|
|
for (int i = 0;i < sample_len;i++) {
|
|
|
|
uint8_t buffer[20];
|
|
|
|
int index = 0;
|
|
|
|
|
|
|
|
buffer[index++] = curr0_samples[i] >> 8;
|
|
|
|
buffer[index++] = curr0_samples[i];
|
|
|
|
buffer[index++] = curr1_samples[i] >> 8;
|
|
|
|
buffer[index++] = curr1_samples[i];
|
|
|
|
buffer[index++] = ph1_samples[i] >> 8;
|
|
|
|
buffer[index++] = ph1_samples[i];
|
|
|
|
buffer[index++] = ph2_samples[i] >> 8;
|
|
|
|
buffer[index++] = ph2_samples[i];
|
|
|
|
buffer[index++] = ph3_samples[i] >> 8;
|
|
|
|
buffer[index++] = ph3_samples[i];
|
|
|
|
buffer[index++] = vzero_samples[i] >> 8;
|
|
|
|
buffer[index++] = vzero_samples[i];
|
|
|
|
buffer[index++] = status_samples[i];
|
|
|
|
buffer[index++] = curr_fir_samples[i] >> 8;
|
|
|
|
buffer[index++] = curr_fir_samples[i];
|
2014-08-05 13:24:13 -07:00
|
|
|
buffer[index++] = f_sw_samples[i] >> 8;
|
|
|
|
buffer[index++] = f_sw_samples[i];
|
2014-01-09 06:20:26 -08:00
|
|
|
|
2014-09-19 18:22:38 -07:00
|
|
|
commands_send_samples(buffer, index);
|
2014-01-09 06:20:26 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-07-19 02:41:16 -07:00
|
|
|
static msg_t timer_thread(void *arg) {
|
|
|
|
(void)arg;
|
|
|
|
|
|
|
|
chRegSetThreadName("msec_timer");
|
|
|
|
|
|
|
|
for(;;) {
|
|
|
|
packet_timerfunc();
|
|
|
|
chThdSleepMilliseconds(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-01-09 06:20:26 -08:00
|
|
|
/*
|
|
|
|
* Called every time new ADC values are available. Note that
|
|
|
|
* the ADC is initialized from mcpwm.c
|
|
|
|
*/
|
|
|
|
void main_dma_adc_handler(void) {
|
|
|
|
ledpwm_update_pwm();
|
|
|
|
|
2014-03-30 05:12:27 -07:00
|
|
|
if (sample_at_start && (mcpwm_get_state() == MC_STATE_RUNNING ||
|
|
|
|
start_comm != mcpwm_get_comm_step())) {
|
2014-01-09 06:20:26 -08:00
|
|
|
sample_now = 0;
|
|
|
|
sample_ready = 0;
|
2014-02-15 14:36:50 -08:00
|
|
|
was_start_sample = 1;
|
2014-01-09 06:20:26 -08:00
|
|
|
sample_at_start = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int a = 0;
|
|
|
|
if (!sample_ready) {
|
|
|
|
a++;
|
|
|
|
if (a >= sample_int) {
|
|
|
|
a = 0;
|
2014-03-13 07:28:56 -07:00
|
|
|
|
|
|
|
if (mcpwm_get_state() == MC_STATE_DETECTING) {
|
|
|
|
curr0_samples[sample_now] = (int16_t)mcpwm_detect_currents[mcpwm_get_comm_step() - 1];
|
2014-04-21 07:17:39 -07:00
|
|
|
curr1_samples[sample_now] = (int16_t)mcpwm_detect_currents_diff[mcpwm_get_comm_step() - 1];
|
2014-03-13 07:28:56 -07:00
|
|
|
} else {
|
|
|
|
curr0_samples[sample_now] = ADC_curr_norm_value[0];
|
2014-04-21 07:17:39 -07:00
|
|
|
curr1_samples[sample_now] = ADC_curr_norm_value[1];
|
2014-03-13 07:28:56 -07:00
|
|
|
}
|
|
|
|
|
2014-03-15 14:32:00 -07:00
|
|
|
ph1_samples[sample_now] = ADC_V_L1 - mcpwm_vzero;
|
|
|
|
ph2_samples[sample_now] = ADC_V_L2 - mcpwm_vzero;
|
|
|
|
ph3_samples[sample_now] = ADC_V_L3 - mcpwm_vzero;
|
|
|
|
vzero_samples[sample_now] = mcpwm_vzero;
|
2014-01-09 06:20:26 -08:00
|
|
|
|
2014-08-05 13:24:13 -07:00
|
|
|
curr_fir_samples[sample_now] = (int16_t)(mcpwm_get_tot_current_filtered() * 100.0);
|
|
|
|
f_sw_samples[sample_now] = (int16_t)(mcpwm_get_switching_frequency_now() / 10.0);
|
2014-03-13 07:28:56 -07:00
|
|
|
|
|
|
|
uint8_t tmp;
|
|
|
|
|
|
|
|
if (was_start_sample) {
|
2014-03-20 14:07:46 -07:00
|
|
|
if (mcpwm_get_state() == MC_STATE_OFF) {
|
2014-03-13 07:28:56 -07:00
|
|
|
tmp = 1;
|
|
|
|
} else if (mcpwm_get_state() == MC_STATE_RUNNING) {
|
|
|
|
tmp = 2;
|
2014-01-09 06:20:26 -08:00
|
|
|
} else {
|
2014-03-13 07:28:56 -07:00
|
|
|
tmp = 3;
|
2014-01-09 06:20:26 -08:00
|
|
|
}
|
2014-03-13 07:28:56 -07:00
|
|
|
} else {
|
|
|
|
tmp = mcpwm_read_hall_phase();
|
2014-01-09 06:20:26 -08:00
|
|
|
}
|
|
|
|
|
2014-03-13 07:28:56 -07:00
|
|
|
status_samples[sample_now] = mcpwm_get_comm_step() | (tmp << 3);
|
2014-01-09 06:20:26 -08:00
|
|
|
|
|
|
|
sample_now++;
|
|
|
|
|
|
|
|
if (sample_now == sample_len) {
|
|
|
|
sample_ready = 1;
|
|
|
|
sample_now = 0;
|
2014-02-15 14:36:50 -08:00
|
|
|
was_start_sample = 0;
|
2014-01-09 06:20:26 -08:00
|
|
|
chSysLockFromIsr();
|
|
|
|
chEvtSignalI(sample_send_tp, (eventmask_t) 1);
|
|
|
|
chSysUnlockFromIsr();
|
|
|
|
}
|
|
|
|
|
|
|
|
main_last_adc_duration = mcpwm_get_last_adc_isr_duration();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
float main_get_last_adc_isr_duration(void) {
|
|
|
|
return main_last_adc_duration;
|
|
|
|
}
|
|
|
|
|
2014-09-14 14:08:22 -07:00
|
|
|
void main_sample_print_data(bool at_start, uint16_t len, uint8_t decimation) {
|
2014-09-17 12:05:57 -07:00
|
|
|
if (len > ADC_SAMPLE_MAX_LEN) {
|
|
|
|
len = ADC_SAMPLE_MAX_LEN;
|
|
|
|
}
|
|
|
|
|
2014-09-14 14:08:22 -07:00
|
|
|
sample_len = len;
|
|
|
|
sample_int = decimation;
|
2014-01-09 06:20:26 -08:00
|
|
|
|
2014-09-14 14:08:22 -07:00
|
|
|
if (at_start) {
|
2014-01-09 06:20:26 -08:00
|
|
|
sample_at_start = 1;
|
2014-03-30 05:12:27 -07:00
|
|
|
start_comm = mcpwm_get_comm_step();
|
2014-09-14 14:08:22 -07:00
|
|
|
} else {
|
|
|
|
sample_now = 0;
|
|
|
|
sample_ready = 0;
|
2014-01-09 06:20:26 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int main(void) {
|
|
|
|
halInit();
|
|
|
|
chSysInit();
|
2014-09-14 17:39:58 -07:00
|
|
|
|
|
|
|
chThdSleepMilliseconds(1000);
|
|
|
|
|
2014-09-14 14:08:22 -07:00
|
|
|
conf_general_init();
|
2014-04-12 12:59:33 -07:00
|
|
|
hw_init_gpio();
|
2014-01-09 06:20:26 -08:00
|
|
|
ledpwm_init();
|
2014-09-14 14:08:22 -07:00
|
|
|
|
|
|
|
mc_configuration mcconf;
|
|
|
|
conf_general_read_mc_configuration(&mcconf);
|
|
|
|
mcpwm_init(&mcconf);
|
|
|
|
|
2014-09-20 04:41:18 -07:00
|
|
|
commands_init();
|
2014-09-19 18:22:38 -07:00
|
|
|
comm_usb_init();
|
2014-12-06 19:30:25 -08:00
|
|
|
comm_can_init();
|
2014-09-17 12:05:57 -07:00
|
|
|
|
|
|
|
app_configuration appconf;
|
|
|
|
conf_general_read_app_configuration(&appconf);
|
|
|
|
app_init(&appconf);
|
2014-09-20 04:41:18 -07:00
|
|
|
timeout_init();
|
|
|
|
timeout_configure(appconf.timeout_msec, appconf.timeout_brake_current);
|
2014-01-09 06:20:26 -08:00
|
|
|
|
2014-12-08 15:11:29 -08:00
|
|
|
#if WS2811_ENABLE
|
|
|
|
ws2811_init();
|
|
|
|
led_external_init();
|
|
|
|
#endif
|
|
|
|
|
2015-04-11 01:07:36 -07:00
|
|
|
// encoder_init();
|
|
|
|
|
2014-01-09 06:20:26 -08:00
|
|
|
// Threads
|
|
|
|
chThdCreateStatic(periodic_thread_wa, sizeof(periodic_thread_wa), NORMALPRIO, periodic_thread, NULL);
|
2014-09-15 11:48:46 -07:00
|
|
|
chThdCreateStatic(sample_send_thread_wa, sizeof(sample_send_thread_wa), NORMALPRIO - 1, sample_send_thread, NULL);
|
2014-07-19 02:41:16 -07:00
|
|
|
chThdCreateStatic(timer_thread_wa, sizeof(timer_thread_wa), NORMALPRIO, timer_thread, NULL);
|
2014-01-09 06:20:26 -08:00
|
|
|
|
|
|
|
for(;;) {
|
|
|
|
chThdSleepMilliseconds(100);
|
|
|
|
}
|
|
|
|
}
|