mirror of https://github.com/rusefi/bldc.git
ADC app added, nunchuk RPM filter, FW version added, feedback on appconf and mcconf set
This commit is contained in:
parent
85f0073105
commit
5a5ccfb4c3
|
@ -39,6 +39,10 @@ void app_init(app_configuration *conf) {
|
||||||
app_ppm_start();
|
app_ppm_start();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case APP_ADC:
|
||||||
|
app_adc_start();
|
||||||
|
break;
|
||||||
|
|
||||||
case APP_UART:
|
case APP_UART:
|
||||||
hw_stop_i2c();
|
hw_stop_i2c();
|
||||||
app_uartcomm_start();
|
app_uartcomm_start();
|
||||||
|
@ -50,6 +54,12 @@ void app_init(app_configuration *conf) {
|
||||||
app_uartcomm_start();
|
app_uartcomm_start();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case APP_ADC_UART:
|
||||||
|
hw_stop_i2c();
|
||||||
|
app_adc_start();
|
||||||
|
app_uartcomm_start();
|
||||||
|
break;
|
||||||
|
|
||||||
case APP_NUNCHUK:
|
case APP_NUNCHUK:
|
||||||
app_nunchuk_start();
|
app_nunchuk_start();
|
||||||
break;
|
break;
|
||||||
|
@ -87,6 +97,7 @@ const app_configuration* app_get_configuration(void) {
|
||||||
void app_set_configuration(app_configuration *conf) {
|
void app_set_configuration(app_configuration *conf) {
|
||||||
appconf = *conf;
|
appconf = *conf;
|
||||||
app_ppm_configure(&appconf.app_ppm_conf);
|
app_ppm_configure(&appconf.app_ppm_conf);
|
||||||
|
app_adc_configure(&appconf.app_adc_conf);
|
||||||
app_uartcomm_configure(appconf.app_uart_baudrate);
|
app_uartcomm_configure(appconf.app_uart_baudrate);
|
||||||
app_nunchuk_configure(&appconf.app_chuk_conf);
|
app_nunchuk_configure(&appconf.app_chuk_conf);
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,10 @@ void app_set_configuration(app_configuration *conf);
|
||||||
// Standard apps
|
// Standard apps
|
||||||
void app_ppm_start(void);
|
void app_ppm_start(void);
|
||||||
void app_ppm_configure(ppm_config *conf);
|
void app_ppm_configure(ppm_config *conf);
|
||||||
|
void app_adc_start(void);
|
||||||
|
void app_adc_configure(adc_config *conf);
|
||||||
|
float app_adc_get_decoded_level(void);
|
||||||
|
float app_adc_get_voltage(void);
|
||||||
void app_uartcomm_start(void);
|
void app_uartcomm_start(void);
|
||||||
void app_uartcomm_configure(uint32_t baudrate);
|
void app_uartcomm_configure(uint32_t baudrate);
|
||||||
void app_nunchuk_start(void);
|
void app_nunchuk_start(void);
|
||||||
|
|
|
@ -0,0 +1,336 @@
|
||||||
|
/*
|
||||||
|
Copyright 2012-2015 Benjamin Vedder benjamin@vedder.se
|
||||||
|
|
||||||
|
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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* app_adc.c
|
||||||
|
*
|
||||||
|
* Created on: 1 may 2015
|
||||||
|
* Author: benjamin
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "app.h"
|
||||||
|
|
||||||
|
#include "ch.h"
|
||||||
|
#include "hal.h"
|
||||||
|
#include "stm32f4xx_conf.h"
|
||||||
|
#include "mcpwm.h"
|
||||||
|
#include "timeout.h"
|
||||||
|
#include "utils.h"
|
||||||
|
#include "comm_can.h"
|
||||||
|
#include "hw.h"
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
// Settings
|
||||||
|
#define MAX_CAN_AGE 0.1
|
||||||
|
#define MIN_MS_WITHOUT_POWER 500
|
||||||
|
#define FILTER_SAMPLES 5
|
||||||
|
|
||||||
|
// Threads
|
||||||
|
static msg_t adc_thread(void *arg);
|
||||||
|
static WORKING_AREA(adc_thread_wa, 1024);
|
||||||
|
|
||||||
|
// Private variables
|
||||||
|
static volatile adc_config config;
|
||||||
|
static volatile float ms_without_power = 0;
|
||||||
|
static volatile float decoded_level = 0.0;
|
||||||
|
static volatile float read_voltage = 0.0;
|
||||||
|
|
||||||
|
void app_adc_configure(adc_config *conf) {
|
||||||
|
config = *conf;
|
||||||
|
ms_without_power = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void app_adc_start(void) {
|
||||||
|
chThdCreateStatic(adc_thread_wa, sizeof(adc_thread_wa), NORMALPRIO, adc_thread, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
float app_adc_get_decoded_level(void) {
|
||||||
|
return decoded_level;
|
||||||
|
}
|
||||||
|
|
||||||
|
float app_adc_get_voltage(void) {
|
||||||
|
return read_voltage;
|
||||||
|
}
|
||||||
|
|
||||||
|
static msg_t adc_thread(void *arg) {
|
||||||
|
(void)arg;
|
||||||
|
|
||||||
|
chRegSetThreadName("APP_ADC");
|
||||||
|
|
||||||
|
// Set servo pin as an input with pullup
|
||||||
|
palSetPadMode(HW_ICU_GPIO, HW_ICU_PIN, PAL_MODE_INPUT_PULLUP);
|
||||||
|
|
||||||
|
for(;;) {
|
||||||
|
// Sleep for a time according to the specified rate
|
||||||
|
systime_t sleep_time = CH_FREQUENCY / config.update_rate_hz;
|
||||||
|
|
||||||
|
// At least one tick should be slept to not block the other threads
|
||||||
|
if (sleep_time == 0) {
|
||||||
|
sleep_time = 1;
|
||||||
|
}
|
||||||
|
chThdSleep(sleep_time);
|
||||||
|
|
||||||
|
// Read the external ADC pin and convert the value to a voltage.
|
||||||
|
float pwr = (float)ADC_Value[ADC_IND_EXT];
|
||||||
|
pwr /= 4095;
|
||||||
|
pwr *= V_REG;
|
||||||
|
|
||||||
|
read_voltage = pwr;
|
||||||
|
|
||||||
|
// Optionally apply a mean value filter
|
||||||
|
if (config.use_filter) {
|
||||||
|
static float filter_buffer[FILTER_SAMPLES];
|
||||||
|
static int filter_ptr = 0;
|
||||||
|
|
||||||
|
filter_buffer[filter_ptr++] = pwr;
|
||||||
|
if (filter_ptr >= FILTER_SAMPLES) {
|
||||||
|
filter_ptr = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pwr = 0.0;
|
||||||
|
for (int i = 0;i < FILTER_SAMPLES;i++) {
|
||||||
|
pwr += filter_buffer[i];
|
||||||
|
}
|
||||||
|
pwr /= FILTER_SAMPLES;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map and truncate the read voltage
|
||||||
|
pwr = utils_map(pwr, config.voltage_start, config.voltage_end, 0.0, 1.0);
|
||||||
|
utils_truncate_number(&pwr, 0.0, 1.0);
|
||||||
|
|
||||||
|
// Optionally invert the read voltage
|
||||||
|
if (config.voltage_inverted) {
|
||||||
|
pwr = 1.0 - pwr;
|
||||||
|
}
|
||||||
|
|
||||||
|
decoded_level = pwr;
|
||||||
|
|
||||||
|
// Read the servo pin and optionally invert it.
|
||||||
|
bool button_val = !palReadPad(HW_ICU_GPIO, HW_ICU_PIN);
|
||||||
|
if (config.button_inverted) {
|
||||||
|
button_val = !button_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (config.ctrl_type) {
|
||||||
|
case ADC_CTRL_TYPE_CURRENT_REV_CENTER:
|
||||||
|
case ADC_CTRL_TYPE_CURRENT_NOREV_BRAKE_CENTER:
|
||||||
|
case ADC_CTRL_TYPE_DUTY_REV_CENTER:
|
||||||
|
// Scale the voltage and set 0 at the center
|
||||||
|
pwr *= 2.0;
|
||||||
|
pwr -= 1.0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ADC_CTRL_TYPE_CURRENT_REV_BUTTON:
|
||||||
|
case ADC_CTRL_TYPE_CURRENT_NOREV_BRAKE_BUTTON:
|
||||||
|
case ADC_CTRL_TYPE_DUTY_REV_BUTTON:
|
||||||
|
// Invert the voltage if the button is pressed
|
||||||
|
if (button_val) {
|
||||||
|
pwr = -pwr;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply a deadband
|
||||||
|
utils_deadband(&pwr, config.hyst, 1.0);
|
||||||
|
|
||||||
|
float current = 0;
|
||||||
|
bool current_mode = false;
|
||||||
|
bool current_mode_brake = false;
|
||||||
|
const volatile mc_configuration *mcconf = mcpwm_get_configuration();
|
||||||
|
bool send_duty = false;
|
||||||
|
|
||||||
|
// Use the filtered and mapped voltage for control according to the configuration.
|
||||||
|
switch (config.ctrl_type) {
|
||||||
|
case ADC_CTRL_TYPE_CURRENT:
|
||||||
|
case ADC_CTRL_TYPE_CURRENT_REV_CENTER:
|
||||||
|
case ADC_CTRL_TYPE_CURRENT_REV_BUTTON:
|
||||||
|
current_mode = true;
|
||||||
|
if (pwr >= 0.0) {
|
||||||
|
current = pwr * mcconf->l_current_max;
|
||||||
|
} else {
|
||||||
|
current = pwr * fabsf(mcconf->l_current_min);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fabsf(pwr) < 0.001) {
|
||||||
|
ms_without_power += (1000.0 * (float)sleep_time) / (float)CH_FREQUENCY;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ADC_CTRL_TYPE_CURRENT_NOREV_BRAKE_CENTER:
|
||||||
|
case ADC_CTRL_TYPE_CURRENT_NOREV_BRAKE_BUTTON:
|
||||||
|
current_mode = true;
|
||||||
|
if (pwr >= 0.0) {
|
||||||
|
current = pwr * mcconf->l_current_max;
|
||||||
|
} else {
|
||||||
|
current = fabsf(pwr * mcconf->l_current_min);
|
||||||
|
current_mode_brake = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pwr < 0.001) {
|
||||||
|
ms_without_power += (1000.0 * (float)sleep_time) / (float)CH_FREQUENCY;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ADC_CTRL_TYPE_DUTY:
|
||||||
|
case ADC_CTRL_TYPE_DUTY_REV_CENTER:
|
||||||
|
case ADC_CTRL_TYPE_DUTY_REV_BUTTON:
|
||||||
|
if (fabsf(pwr) < 0.001) {
|
||||||
|
ms_without_power += (1000.0 * (float)sleep_time) / (float)CH_FREQUENCY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(ms_without_power < MIN_MS_WITHOUT_POWER && config.safe_start)) {
|
||||||
|
mcpwm_set_duty(pwr);
|
||||||
|
send_duty = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If safe start is enabled and the output has not been zero for long enough
|
||||||
|
if (ms_without_power < MIN_MS_WITHOUT_POWER && config.safe_start) {
|
||||||
|
static int pulses_without_power_before = 0;
|
||||||
|
if (ms_without_power == pulses_without_power_before) {
|
||||||
|
ms_without_power = 0;
|
||||||
|
}
|
||||||
|
pulses_without_power_before = ms_without_power;
|
||||||
|
mcpwm_set_current(0.0);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset timeout
|
||||||
|
timeout_reset();
|
||||||
|
|
||||||
|
// Find lowest RPM (for traction control)
|
||||||
|
float rpm_local = mcpwm_get_rpm();
|
||||||
|
float rpm_lowest = rpm_local;
|
||||||
|
if (config.multi_esc) {
|
||||||
|
for (int i = 0;i < CAN_STATUS_MSGS_TO_STORE;i++) {
|
||||||
|
can_status_msg *msg = comm_can_get_status_msg_index(i);
|
||||||
|
|
||||||
|
if (msg->id >= 0 && UTILS_AGE_S(msg->rx_time) < MAX_CAN_AGE) {
|
||||||
|
float rpm_tmp = msg->rpm;
|
||||||
|
|
||||||
|
if (fabsf(rpm_tmp) < fabsf(rpm_lowest)) {
|
||||||
|
rpm_lowest = rpm_tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Optionally send the duty cycles to the other ESCs seen on the CAN-bus
|
||||||
|
if (send_duty && config.multi_esc) {
|
||||||
|
float duty = mcpwm_get_duty_cycle_now();
|
||||||
|
|
||||||
|
for (int i = 0;i < CAN_STATUS_MSGS_TO_STORE;i++) {
|
||||||
|
can_status_msg *msg = comm_can_get_status_msg_index(i);
|
||||||
|
|
||||||
|
if (msg->id >= 0 && UTILS_AGE_S(msg->rx_time) < MAX_CAN_AGE) {
|
||||||
|
comm_can_set_duty(msg->id, duty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current_mode) {
|
||||||
|
if (current_mode_brake) {
|
||||||
|
mcpwm_set_brake_current(current);
|
||||||
|
|
||||||
|
// Send brake command to all ESCs seen recently on the CAN bus
|
||||||
|
for (int i = 0;i < CAN_STATUS_MSGS_TO_STORE;i++) {
|
||||||
|
can_status_msg *msg = comm_can_get_status_msg_index(i);
|
||||||
|
|
||||||
|
if (msg->id >= 0 && UTILS_AGE_S(msg->rx_time) < MAX_CAN_AGE) {
|
||||||
|
comm_can_set_current_brake(msg->id, current);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Apply soft RPM limit
|
||||||
|
if (rpm_lowest > config.rpm_lim_end && current > 0.0) {
|
||||||
|
current = mcconf->cc_min_current;
|
||||||
|
} else if (rpm_lowest > config.rpm_lim_start && current > 0.0) {
|
||||||
|
current = utils_map(rpm_lowest, config.rpm_lim_start, config.rpm_lim_end, current, mcconf->cc_min_current);
|
||||||
|
} else if (rpm_lowest < -config.rpm_lim_end && current < 0.0) {
|
||||||
|
current = mcconf->cc_min_current;
|
||||||
|
} else if (rpm_lowest < -config.rpm_lim_start && current < 0.0) {
|
||||||
|
rpm_lowest = -rpm_lowest;
|
||||||
|
current = -current;
|
||||||
|
current = utils_map(rpm_lowest, config.rpm_lim_start, config.rpm_lim_end, current, mcconf->cc_min_current);
|
||||||
|
current = -current;
|
||||||
|
rpm_lowest = -rpm_lowest;
|
||||||
|
}
|
||||||
|
|
||||||
|
float current_out = current;
|
||||||
|
bool is_reverse = false;
|
||||||
|
if (current_out < 0.0) {
|
||||||
|
is_reverse = true;
|
||||||
|
current_out = -current_out;
|
||||||
|
current = -current;
|
||||||
|
rpm_local = -rpm_local;
|
||||||
|
rpm_lowest = -rpm_lowest;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Traction control
|
||||||
|
if (config.multi_esc) {
|
||||||
|
for (int i = 0;i < CAN_STATUS_MSGS_TO_STORE;i++) {
|
||||||
|
can_status_msg *msg = comm_can_get_status_msg_index(i);
|
||||||
|
|
||||||
|
if (msg->id >= 0 && UTILS_AGE_S(msg->rx_time) < MAX_CAN_AGE) {
|
||||||
|
if (config.tc) {
|
||||||
|
float rpm_tmp = msg->rpm;
|
||||||
|
if (is_reverse) {
|
||||||
|
rpm_tmp = -rpm_tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
float diff = rpm_tmp - rpm_lowest;
|
||||||
|
current_out = utils_map(diff, 0.0, config.tc_max_diff, current, 0.0);
|
||||||
|
if (current_out < mcconf->cc_min_current) {
|
||||||
|
current_out = 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_reverse) {
|
||||||
|
comm_can_set_current(msg->id, -current_out);
|
||||||
|
} else {
|
||||||
|
comm_can_set_current(msg->id, current_out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.tc) {
|
||||||
|
float diff = rpm_local - rpm_lowest;
|
||||||
|
current_out = utils_map(diff, 0.0, config.tc_max_diff, current, 0.0);
|
||||||
|
if (current_out < mcconf->cc_min_current) {
|
||||||
|
current_out = 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_reverse) {
|
||||||
|
mcpwm_set_current(-current_out);
|
||||||
|
} else {
|
||||||
|
mcpwm_set_current(current_out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -40,6 +40,7 @@
|
||||||
#define OUTPUT_ITERATION_TIME_MS 1
|
#define OUTPUT_ITERATION_TIME_MS 1
|
||||||
#define MAX_CURR_DIFFERENCE 5.0
|
#define MAX_CURR_DIFFERENCE 5.0
|
||||||
#define MAX_CAN_AGE 0.1
|
#define MAX_CAN_AGE 0.1
|
||||||
|
#define RPM_FILTER_SAMPLES 8
|
||||||
|
|
||||||
// Threads
|
// Threads
|
||||||
static msg_t chuk_thread(void *arg);
|
static msg_t chuk_thread(void *arg);
|
||||||
|
@ -230,12 +231,27 @@ static msg_t output_thread(void *arg) {
|
||||||
// If c is pressed and no throttle is used, maintain the current speed with PID control
|
// If c is pressed and no throttle is used, maintain the current speed with PID control
|
||||||
static bool was_pid = false;
|
static bool was_pid = false;
|
||||||
|
|
||||||
|
// Filter RPM to avoid glitches
|
||||||
|
static float filter_buffer[RPM_FILTER_SAMPLES];
|
||||||
|
static int filter_ptr = 0;
|
||||||
|
float rpm_filtered = mcpwm_get_rpm();
|
||||||
|
filter_buffer[filter_ptr++] = rpm_filtered;
|
||||||
|
if (filter_ptr >= RPM_FILTER_SAMPLES) {
|
||||||
|
filter_ptr = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
rpm_filtered = 0.0;
|
||||||
|
for (int i = 0;i < RPM_FILTER_SAMPLES;i++) {
|
||||||
|
rpm_filtered += filter_buffer[i];
|
||||||
|
}
|
||||||
|
rpm_filtered /= RPM_FILTER_SAMPLES;
|
||||||
|
|
||||||
if (chuck_d.bt_c && out_val == 0.0) {
|
if (chuck_d.bt_c && out_val == 0.0) {
|
||||||
static float pid_rpm = 0.0;
|
static float pid_rpm = 0.0;
|
||||||
|
|
||||||
if (!was_pid) {
|
if (!was_pid) {
|
||||||
was_pid = true;
|
was_pid = true;
|
||||||
pid_rpm = mcpwm_get_rpm();
|
pid_rpm = rpm_filtered;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((is_reverse && pid_rpm < 0.0) || (!is_reverse && pid_rpm > 0.0)) {
|
if ((is_reverse && pid_rpm < 0.0) || (!is_reverse && pid_rpm > 0.0)) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2012-2014 Benjamin Vedder benjamin@vedder.se
|
Copyright 2012-2015 Benjamin Vedder benjamin@vedder.se
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -53,7 +53,7 @@ static volatile ppm_config config;
|
||||||
static volatile int pulses_without_power = 0;
|
static volatile int pulses_without_power = 0;
|
||||||
|
|
||||||
// Private functions
|
// Private functions
|
||||||
void update(void *p);
|
static void update(void *p);
|
||||||
|
|
||||||
void app_ppm_configure(ppm_config *conf) {
|
void app_ppm_configure(ppm_config *conf) {
|
||||||
config = *conf;
|
config = *conf;
|
||||||
|
@ -79,7 +79,7 @@ static void servodec_func(void) {
|
||||||
chSysUnlockFromIsr();
|
chSysUnlockFromIsr();
|
||||||
}
|
}
|
||||||
|
|
||||||
void update(void *p) {
|
static void update(void *p) {
|
||||||
chSysLockFromIsr();
|
chSysLockFromIsr();
|
||||||
chVTSetI(&vt, MS2ST(2), update, p);
|
chVTSetI(&vt, MS2ST(2), update, p);
|
||||||
chEvtSignalI(ppm_tp, (eventmask_t) 1);
|
chEvtSignalI(ppm_tp, (eventmask_t) 1);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
APPSRC = applications/app.c \
|
APPSRC = applications/app.c \
|
||||||
applications/app_ppm.c \
|
applications/app_ppm.c \
|
||||||
|
applications/app_adc.c \
|
||||||
applications/app_sten.c \
|
applications/app_sten.c \
|
||||||
applications/app_gurgalof.c \
|
applications/app_gurgalof.c \
|
||||||
applications/app_uartcomm.c \
|
applications/app_uartcomm.c \
|
||||||
|
|
|
@ -239,7 +239,12 @@ static msg_t cancom_status_thread(void *arg) {
|
||||||
comm_can_transmit(app_get_configuration()->controller_id | ((uint32_t)CAN_PACKET_STATUS << 8), buffer, send_index);
|
comm_can_transmit(app_get_configuration()->controller_id | ((uint32_t)CAN_PACKET_STATUS << 8), buffer, send_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
chThdSleep(CH_FREQUENCY / app_get_configuration()->send_can_status_rate_hz);
|
systime_t sleep_time = CH_FREQUENCY / app_get_configuration()->send_can_status_rate_hz;
|
||||||
|
if (sleep_time == 0) {
|
||||||
|
sleep_time = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
chThdSleep(sleep_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
54
commands.c
54
commands.c
|
@ -115,6 +115,14 @@ void commands_process_packet(unsigned char *data, unsigned char len) {
|
||||||
len--;
|
len--;
|
||||||
|
|
||||||
switch (packet_id) {
|
switch (packet_id) {
|
||||||
|
case COMM_FW_VERSION:
|
||||||
|
ind = 0;
|
||||||
|
send_buffer[ind++] = COMM_FW_VERSION;
|
||||||
|
send_buffer[ind++] = FW_VERSION_MAJOR;
|
||||||
|
send_buffer[ind++] = FW_VERSION_MINOR;
|
||||||
|
commands_send_packet(send_buffer, ind);
|
||||||
|
break;
|
||||||
|
|
||||||
case COMM_GET_VALUES:
|
case COMM_GET_VALUES:
|
||||||
ind = 0;
|
ind = 0;
|
||||||
send_buffer[ind++] = COMM_GET_VALUES;
|
send_buffer[ind++] = COMM_GET_VALUES;
|
||||||
|
@ -241,6 +249,10 @@ void commands_process_packet(unsigned char *data, unsigned char len) {
|
||||||
|
|
||||||
conf_general_store_mc_configuration(&mcconf);
|
conf_general_store_mc_configuration(&mcconf);
|
||||||
mcpwm_set_configuration(&mcconf);
|
mcpwm_set_configuration(&mcconf);
|
||||||
|
|
||||||
|
ind = 0;
|
||||||
|
send_buffer[ind++] = COMM_SET_MCCONF;
|
||||||
|
commands_send_packet(send_buffer, ind);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case COMM_GET_MCCONF:
|
case COMM_GET_MCCONF:
|
||||||
|
@ -328,6 +340,21 @@ void commands_process_packet(unsigned char *data, unsigned char len) {
|
||||||
appconf.app_ppm_conf.tc = data[ind++];
|
appconf.app_ppm_conf.tc = data[ind++];
|
||||||
appconf.app_ppm_conf.tc_max_diff = (float)buffer_get_int32(data, &ind) / 1000.0;
|
appconf.app_ppm_conf.tc_max_diff = (float)buffer_get_int32(data, &ind) / 1000.0;
|
||||||
|
|
||||||
|
appconf.app_adc_conf.ctrl_type = data[ind++];
|
||||||
|
appconf.app_adc_conf.hyst = (float)buffer_get_int32(data, &ind) / 1000.0;
|
||||||
|
appconf.app_adc_conf.voltage_start = (float)buffer_get_int32(data, &ind) / 1000.0;
|
||||||
|
appconf.app_adc_conf.voltage_end = (float)buffer_get_int32(data, &ind) / 1000.0;
|
||||||
|
appconf.app_adc_conf.use_filter = data[ind++];
|
||||||
|
appconf.app_adc_conf.safe_start = data[ind++];
|
||||||
|
appconf.app_adc_conf.button_inverted = data[ind++];
|
||||||
|
appconf.app_adc_conf.voltage_inverted = data[ind++];
|
||||||
|
appconf.app_adc_conf.rpm_lim_start = (float)buffer_get_int32(data, &ind) / 1000.0;
|
||||||
|
appconf.app_adc_conf.rpm_lim_end = (float)buffer_get_int32(data, &ind) / 1000.0;
|
||||||
|
appconf.app_adc_conf.multi_esc = data[ind++];
|
||||||
|
appconf.app_adc_conf.tc = data[ind++];
|
||||||
|
appconf.app_adc_conf.tc_max_diff = (float)buffer_get_int32(data, &ind) / 1000.0;
|
||||||
|
appconf.app_adc_conf.update_rate_hz = buffer_get_uint16(data, &ind);
|
||||||
|
|
||||||
appconf.app_uart_baudrate = buffer_get_uint32(data, &ind);
|
appconf.app_uart_baudrate = buffer_get_uint32(data, &ind);
|
||||||
|
|
||||||
appconf.app_chuk_conf.ctrl_type = data[ind++];
|
appconf.app_chuk_conf.ctrl_type = data[ind++];
|
||||||
|
@ -343,6 +370,10 @@ void commands_process_packet(unsigned char *data, unsigned char len) {
|
||||||
conf_general_store_app_configuration(&appconf);
|
conf_general_store_app_configuration(&appconf);
|
||||||
app_set_configuration(&appconf);
|
app_set_configuration(&appconf);
|
||||||
timeout_configure(appconf.timeout_msec, appconf.timeout_brake_current);
|
timeout_configure(appconf.timeout_msec, appconf.timeout_brake_current);
|
||||||
|
|
||||||
|
ind = 0;
|
||||||
|
send_buffer[ind++] = COMM_SET_MCCONF;
|
||||||
|
commands_send_packet(send_buffer, ind);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case COMM_GET_APPCONF:
|
case COMM_GET_APPCONF:
|
||||||
|
@ -371,6 +402,21 @@ void commands_process_packet(unsigned char *data, unsigned char len) {
|
||||||
send_buffer[ind++] = appconf.app_ppm_conf.tc;
|
send_buffer[ind++] = appconf.app_ppm_conf.tc;
|
||||||
buffer_append_int32(send_buffer, (int32_t)(appconf.app_ppm_conf.tc_max_diff * 1000.0), &ind);
|
buffer_append_int32(send_buffer, (int32_t)(appconf.app_ppm_conf.tc_max_diff * 1000.0), &ind);
|
||||||
|
|
||||||
|
send_buffer[ind++] = appconf.app_adc_conf.ctrl_type;
|
||||||
|
buffer_append_int32(send_buffer, (int32_t)(appconf.app_adc_conf.hyst * 1000.0), &ind);
|
||||||
|
buffer_append_int32(send_buffer, (int32_t)(appconf.app_adc_conf.voltage_start * 1000.0), &ind);
|
||||||
|
buffer_append_int32(send_buffer, (int32_t)(appconf.app_adc_conf.voltage_end * 1000.0), &ind);
|
||||||
|
send_buffer[ind++] = appconf.app_adc_conf.use_filter;
|
||||||
|
send_buffer[ind++] = appconf.app_adc_conf.safe_start;
|
||||||
|
send_buffer[ind++] = appconf.app_adc_conf.button_inverted;
|
||||||
|
send_buffer[ind++] = appconf.app_adc_conf.voltage_inverted;
|
||||||
|
buffer_append_int32(send_buffer, (int32_t)(appconf.app_adc_conf.rpm_lim_start * 1000.0), &ind);
|
||||||
|
buffer_append_int32(send_buffer, (int32_t)(appconf.app_adc_conf.rpm_lim_end * 1000.0), &ind);
|
||||||
|
send_buffer[ind++] = appconf.app_adc_conf.multi_esc;
|
||||||
|
send_buffer[ind++] = appconf.app_adc_conf.tc;
|
||||||
|
buffer_append_int32(send_buffer, (int32_t)(appconf.app_adc_conf.tc_max_diff * 1000.0), &ind);
|
||||||
|
buffer_append_uint16(send_buffer, appconf.app_adc_conf.update_rate_hz, &ind);
|
||||||
|
|
||||||
buffer_append_uint32(send_buffer, appconf.app_uart_baudrate, &ind);
|
buffer_append_uint32(send_buffer, appconf.app_uart_baudrate, &ind);
|
||||||
|
|
||||||
send_buffer[ind++] = appconf.app_chuk_conf.ctrl_type;
|
send_buffer[ind++] = appconf.app_chuk_conf.ctrl_type;
|
||||||
|
@ -426,6 +472,14 @@ void commands_process_packet(unsigned char *data, unsigned char len) {
|
||||||
commands_send_packet(send_buffer, ind);
|
commands_send_packet(send_buffer, ind);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case COMM_GET_DECODED_ADC:
|
||||||
|
ind = 0;
|
||||||
|
send_buffer[ind++] = COMM_GET_DECODED_ADC;
|
||||||
|
buffer_append_int32(send_buffer, (int32_t)(app_adc_get_decoded_level() * 1000000.0), &ind);
|
||||||
|
buffer_append_int32(send_buffer, (int32_t)(app_adc_get_voltage() * 1000000.0), &ind);
|
||||||
|
commands_send_packet(send_buffer, ind);
|
||||||
|
break;
|
||||||
|
|
||||||
case COMM_GET_DECODED_CHUK:
|
case COMM_GET_DECODED_CHUK:
|
||||||
ind = 0;
|
ind = 0;
|
||||||
send_buffer[ind++] = COMM_GET_DECODED_CHUK;
|
send_buffer[ind++] = COMM_GET_DECODED_CHUK;
|
||||||
|
|
|
@ -152,19 +152,34 @@ void conf_general_read_app_configuration(app_configuration *conf) {
|
||||||
|
|
||||||
conf->app_to_use = APP_NONE;
|
conf->app_to_use = APP_NONE;
|
||||||
|
|
||||||
conf->app_ppm_conf.ctrl_type = PPM_CTRL_TYPE_CURRENT;
|
conf->app_ppm_conf.ctrl_type = PPM_CTRL_TYPE_NONE;
|
||||||
conf->app_ppm_conf.pid_max_erpm = 15000;
|
conf->app_ppm_conf.pid_max_erpm = 15000;
|
||||||
conf->app_ppm_conf.hyst = 0.15;
|
conf->app_ppm_conf.hyst = 0.15;
|
||||||
conf->app_ppm_conf.pulse_start = 1.0;
|
conf->app_ppm_conf.pulse_start = 1.0;
|
||||||
conf->app_ppm_conf.pulse_end = 2.0;
|
conf->app_ppm_conf.pulse_end = 2.0;
|
||||||
conf->app_ppm_conf.median_filter = false;
|
conf->app_ppm_conf.median_filter = false;
|
||||||
conf->app_ppm_conf.safe_start = false;
|
conf->app_ppm_conf.safe_start = true;
|
||||||
conf->app_ppm_conf.rpm_lim_start = 150000.0;
|
conf->app_ppm_conf.rpm_lim_start = 150000.0;
|
||||||
conf->app_ppm_conf.rpm_lim_end = 200000.0;
|
conf->app_ppm_conf.rpm_lim_end = 200000.0;
|
||||||
conf->app_ppm_conf.multi_esc = true;
|
conf->app_ppm_conf.multi_esc = false;
|
||||||
conf->app_ppm_conf.tc = false;
|
conf->app_ppm_conf.tc = false;
|
||||||
conf->app_ppm_conf.tc_max_diff = 3000.0;
|
conf->app_ppm_conf.tc_max_diff = 3000.0;
|
||||||
|
|
||||||
|
conf->app_adc_conf.ctrl_type = ADC_CTRL_TYPE_NONE;
|
||||||
|
conf->app_adc_conf.hyst = 0.15;
|
||||||
|
conf->app_adc_conf.voltage_start = 0.9;
|
||||||
|
conf->app_adc_conf.voltage_end = 3.0;
|
||||||
|
conf->app_adc_conf.use_filter = true;
|
||||||
|
conf->app_adc_conf.safe_start = true;
|
||||||
|
conf->app_adc_conf.button_inverted = false;
|
||||||
|
conf->app_adc_conf.voltage_inverted = false;
|
||||||
|
conf->app_adc_conf.rpm_lim_start = 150000;
|
||||||
|
conf->app_adc_conf.rpm_lim_end = 200000;
|
||||||
|
conf->app_adc_conf.multi_esc = false;
|
||||||
|
conf->app_adc_conf.tc = false;
|
||||||
|
conf->app_adc_conf.tc_max_diff = 3000.0;
|
||||||
|
conf->app_adc_conf.update_rate_hz = 500;
|
||||||
|
|
||||||
conf->app_uart_baudrate = 115200;
|
conf->app_uart_baudrate = 115200;
|
||||||
|
|
||||||
conf->app_chuk_conf.ctrl_type = CHUK_CTRL_TYPE_CURRENT;
|
conf->app_chuk_conf.ctrl_type = CHUK_CTRL_TYPE_CURRENT;
|
||||||
|
|
|
@ -25,6 +25,10 @@
|
||||||
#ifndef CONF_GENERAL_H_
|
#ifndef CONF_GENERAL_H_
|
||||||
#define CONF_GENERAL_H_
|
#define CONF_GENERAL_H_
|
||||||
|
|
||||||
|
// Software version
|
||||||
|
#define FW_VERSION_MAJOR 1
|
||||||
|
#define FW_VERSION_MINOR 0
|
||||||
|
|
||||||
#include "datatypes.h"
|
#include "datatypes.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
39
datatypes.h
39
datatypes.h
|
@ -145,8 +145,10 @@ typedef struct {
|
||||||
typedef enum {
|
typedef enum {
|
||||||
APP_NONE = 0,
|
APP_NONE = 0,
|
||||||
APP_PPM,
|
APP_PPM,
|
||||||
|
APP_ADC,
|
||||||
APP_UART,
|
APP_UART,
|
||||||
APP_PPM_UART,
|
APP_PPM_UART,
|
||||||
|
APP_ADC_UART,
|
||||||
APP_NUNCHUK,
|
APP_NUNCHUK,
|
||||||
APP_NRF,
|
APP_NRF,
|
||||||
APP_CUSTOM
|
APP_CUSTOM
|
||||||
|
@ -179,6 +181,36 @@ typedef struct {
|
||||||
float tc_max_diff;
|
float tc_max_diff;
|
||||||
} ppm_config;
|
} ppm_config;
|
||||||
|
|
||||||
|
// ADC control types
|
||||||
|
typedef enum {
|
||||||
|
ADC_CTRL_TYPE_NONE = 0,
|
||||||
|
ADC_CTRL_TYPE_CURRENT,
|
||||||
|
ADC_CTRL_TYPE_CURRENT_REV_CENTER,
|
||||||
|
ADC_CTRL_TYPE_CURRENT_REV_BUTTON,
|
||||||
|
ADC_CTRL_TYPE_CURRENT_NOREV_BRAKE_CENTER,
|
||||||
|
ADC_CTRL_TYPE_CURRENT_NOREV_BRAKE_BUTTON,
|
||||||
|
ADC_CTRL_TYPE_DUTY,
|
||||||
|
ADC_CTRL_TYPE_DUTY_REV_CENTER,
|
||||||
|
ADC_CTRL_TYPE_DUTY_REV_BUTTON
|
||||||
|
} adc_control_type;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
adc_control_type ctrl_type;
|
||||||
|
float hyst;
|
||||||
|
float voltage_start;
|
||||||
|
float voltage_end;
|
||||||
|
bool use_filter;
|
||||||
|
bool safe_start;
|
||||||
|
bool button_inverted;
|
||||||
|
bool voltage_inverted;
|
||||||
|
float rpm_lim_start;
|
||||||
|
float rpm_lim_end;
|
||||||
|
bool multi_esc;
|
||||||
|
bool tc;
|
||||||
|
float tc_max_diff;
|
||||||
|
uint32_t update_rate_hz;
|
||||||
|
} adc_config;
|
||||||
|
|
||||||
// Nunchuk control types
|
// Nunchuk control types
|
||||||
typedef enum {
|
typedef enum {
|
||||||
CHUK_CTRL_TYPE_NONE = 0,
|
CHUK_CTRL_TYPE_NONE = 0,
|
||||||
|
@ -212,6 +244,9 @@ typedef struct {
|
||||||
// PPM application settings
|
// PPM application settings
|
||||||
ppm_config app_ppm_conf;
|
ppm_config app_ppm_conf;
|
||||||
|
|
||||||
|
// ADC application settings
|
||||||
|
adc_config app_adc_conf;
|
||||||
|
|
||||||
// UART application settings
|
// UART application settings
|
||||||
uint32_t app_uart_baudrate;
|
uint32_t app_uart_baudrate;
|
||||||
|
|
||||||
|
@ -221,7 +256,8 @@ typedef struct {
|
||||||
|
|
||||||
// Communication commands
|
// Communication commands
|
||||||
typedef enum {
|
typedef enum {
|
||||||
COMM_GET_VALUES = 0,
|
COMM_FW_VERSION = 0,
|
||||||
|
COMM_GET_VALUES,
|
||||||
COMM_SET_DUTY,
|
COMM_SET_DUTY,
|
||||||
COMM_SET_CURRENT,
|
COMM_SET_CURRENT,
|
||||||
COMM_SET_CURRENT_BRAKE,
|
COMM_SET_CURRENT_BRAKE,
|
||||||
|
@ -242,6 +278,7 @@ typedef enum {
|
||||||
COMM_REBOOT,
|
COMM_REBOOT,
|
||||||
COMM_ALIVE,
|
COMM_ALIVE,
|
||||||
COMM_GET_DECODED_PPM,
|
COMM_GET_DECODED_PPM,
|
||||||
|
COMM_GET_DECODED_ADC,
|
||||||
COMM_GET_DECODED_CHUK,
|
COMM_GET_DECODED_CHUK,
|
||||||
COMM_FORWARD_CAN
|
COMM_FORWARD_CAN
|
||||||
} COMM_PACKET_ID;
|
} COMM_PACKET_ID;
|
||||||
|
|
Loading…
Reference in New Issue