Skip to content

Commit

Permalink
Merge pull request #323 from tinymovr/develop
Browse files Browse the repository at this point in the history
Version 1.6.5
  • Loading branch information
yconst authored Feb 17, 2024
2 parents e127e30 + 89b3b18 commit fdfd668
Show file tree
Hide file tree
Showing 30 changed files with 424 additions and 336 deletions.
6 changes: 3 additions & 3 deletions .readthedocs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@ sphinx:

# We recommend specifying your dependencies to enable reproducible builds:
# https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
# python:
# install:
# - requirements: docs/requirements.txt
python:
install:
- requirements: docs/requirements.txt
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
![Docs Build](https://github.com/yconst/tinymovr/workflows/Tinymovr%20Docs%20Build/badge.svg)
[![Discord](https://img.shields.io/discord/742400176664084535)](https://discord.gg/CzcCaXbU)

[Tinymovr is an affordable motor controller](https://tinymovr.com) for precise control of 3-phase brushless motors. Tinymovr works with up to 38V input voltage, drives motors up to 40A continuous phase current, integrates an absolute angle encoder (MPS MA702) and features rich connectivity.
[Tinymovr is an affordable motor controller](https://tinymovr.com) with integrated encoder and CAN bus for precise control of 3-phase brushless motors (PMSMs).

This repository holds the open source firmware, client library, hardware designs and documentation source.

Expand Down
2 changes: 1 addition & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'alabaster'
html_theme = 'furo'

# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
Expand Down
6 changes: 5 additions & 1 deletion docs/requirements.txt
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
sphinx>=3.2.1
sphinx>=5.2.3
sphinxcontrib-programoutput
sphinx-inline-tabs
sphinx-copybutton
furo
17 changes: 9 additions & 8 deletions firmware/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ all: release
debug: CFLAGS += -DDEBUG -g2 -O1
debug: CPPFLAGS += -DDEBUG -g2 -O1
debug: LDFLAGS += -O1
debug: OBJECTS += $(BUILDDIR)/bootloader_$(REV).o
debug: OBJECTS += $(BUILDDIR)/bootloader-$(REV).o
debug: binary

# Upgrade target
Expand All @@ -114,11 +114,11 @@ upgrade: LDFLAGS += -O3
upgrade: binary

# Release target
release: OBJECTS += $(BUILDDIR)/bootloader_$(REV).o
release: OBJECTS += $(BUILDDIR)/bootloader-$(REV).o
release: upgrade

# Binary target
binary: print_board_rev $(HEX) $(BIN) $(ELF)
binary: print_board_info $(HEX) $(BIN) $(ELF)

# Objcopy to HEX
$(HEX): $(ELF)
Expand All @@ -131,7 +131,7 @@ $(BIN): $(ELF)

# Link
$(ELF): $(OBJECTS)
- $(OBJCOPY) -I binary -O elf32-littlearm -B arm --rename-section .data=.bl_section,alloc,load,readonly,data,contents $(PROJECTDIR)/bootloader/bootloader_$(REV).bin $(BUILDDIR)/bootloader_$(REV).o
- $(OBJCOPY) -I binary -O elf32-littlearm -B arm --rename-section .data=.bl_section,alloc,load,readonly,data,contents $(PROJECTDIR)/bootloader/bootloader-$(REV).bin $(BUILDDIR)/bootloader-$(REV).o
$(LD) $(LDFLAGS) $(OBJECTS) -o $(ELF)
$(SIZE_EX) --format=berkeley $(ELF)

Expand All @@ -151,8 +151,9 @@ clean :
- $(rmdir_cmd) "$(BUILDDIR)"

# Print board revision
.PHONY: print_board_rev
print_board_rev:
@echo "===Building Tinymovr==="
.PHONY: print_board_info
print_board_info:
@echo "===Building Tinymovr Bootloader==="
@echo "Board revision is $(REV)"
@echo "======================="
@echo "Fw version is $(GIT_VERSION)"
@echo "=================================="
Binary file added firmware/bootloader/bootloader-M51.bin
Binary file not shown.
Binary file added firmware/bootloader/bootloader-R32.bin
Binary file not shown.
Binary file added firmware/bootloader/bootloader-R33.bin
Binary file not shown.
Binary file added firmware/bootloader/bootloader-R50.bin
Binary file not shown.
Binary file added firmware/bootloader/bootloader-R51.bin
Binary file not shown.
Binary file added firmware/bootloader/bootloader-R52.bin
Binary file not shown.
Binary file removed firmware/bootloader/bootloader_M51.bin
Binary file not shown.
Binary file removed firmware/bootloader/bootloader_R32.bin
Binary file not shown.
Binary file removed firmware/bootloader/bootloader_R33.bin
Binary file not shown.
Binary file removed firmware/bootloader/bootloader_R50.bin
Binary file not shown.
Binary file removed firmware/bootloader/bootloader_R51.bin
Binary file not shown.
Binary file removed firmware/bootloader/bootloader_R52.bin
Binary file not shown.
6 changes: 5 additions & 1 deletion firmware/src/can/can.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ static CANState state ={0};

extern volatile uint32_t msTicks;

const uint8_t avlos_proto_hash_8 = (uint8_t)(avlos_proto_hash & 0xFF);
const size_t endpoint_count = sizeof(avlos_endpoints) / sizeof(avlos_endpoints[0]);

void CAN_init(void)
{
#if defined(BOARD_REV_R52)
Expand Down Expand Up @@ -135,7 +138,8 @@ void CAN_process_interrupt(void)
{
can_process_extended();

if (sizeof(avlos_endpoints) / sizeof(avlos_endpoints[0]) > can_ep_id)
if ((endpoint_count > can_ep_id) &&
((can_frame_hash == avlos_proto_hash_8) || (can_frame_hash == 0)))
{
uint8_t (*callback)(uint8_t buffer[], uint8_t * buffer_length, Avlos_Command cmd) = avlos_endpoints[can_ep_id];
uint8_t can_msg_buffer[8];
Expand Down
1 change: 0 additions & 1 deletion firmware/src/can/can_endpoints.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@


uint8_t (*avlos_endpoints[79])(uint8_t * buffer, uint8_t * buffer_len, Avlos_Command cmd) = {&avlos_protocol_hash, &avlos_uid, &avlos_fw_version, &avlos_hw_revision, &avlos_Vbus, &avlos_Ibus, &avlos_power, &avlos_temp, &avlos_calibrated, &avlos_errors, &avlos_save_config, &avlos_erase_config, &avlos_reset, &avlos_enter_dfu, &avlos_scheduler_errors, &avlos_controller_state, &avlos_controller_mode, &avlos_controller_warnings, &avlos_controller_errors, &avlos_controller_position_setpoint, &avlos_controller_position_p_gain, &avlos_controller_velocity_setpoint, &avlos_controller_velocity_limit, &avlos_controller_velocity_p_gain, &avlos_controller_velocity_i_gain, &avlos_controller_velocity_deadband, &avlos_controller_velocity_increment, &avlos_controller_current_Iq_setpoint, &avlos_controller_current_Id_setpoint, &avlos_controller_current_Iq_limit, &avlos_controller_current_Iq_estimate, &avlos_controller_current_bandwidth, &avlos_controller_current_Iq_p_gain, &avlos_controller_current_max_Ibus_regen, &avlos_controller_current_max_Ibrake, &avlos_controller_voltage_Vq_setpoint, &avlos_controller_calibrate, &avlos_controller_idle, &avlos_controller_position_mode, &avlos_controller_velocity_mode, &avlos_controller_current_mode, &avlos_controller_set_pos_vel_setpoints, &avlos_comms_can_rate, &avlos_comms_can_id, &avlos_motor_R, &avlos_motor_L, &avlos_motor_pole_pairs, &avlos_motor_type, &avlos_motor_offset, &avlos_motor_direction, &avlos_motor_calibrated, &avlos_motor_I_cal, &avlos_motor_errors, &avlos_encoder_position_estimate, &avlos_encoder_velocity_estimate, &avlos_encoder_type, &avlos_encoder_bandwidth, &avlos_encoder_calibrated, &avlos_encoder_errors, &avlos_traj_planner_max_accel, &avlos_traj_planner_max_decel, &avlos_traj_planner_max_vel, &avlos_traj_planner_t_accel, &avlos_traj_planner_t_decel, &avlos_traj_planner_t_total, &avlos_traj_planner_move_to, &avlos_traj_planner_move_to_tlimit, &avlos_traj_planner_errors, &avlos_homing_velocity, &avlos_homing_max_homing_t, &avlos_homing_retract_dist, &avlos_homing_warnings, &avlos_homing_stall_detect_velocity, &avlos_homing_stall_detect_delta_pos, &avlos_homing_stall_detect_t, &avlos_homing_home, &avlos_watchdog_enabled, &avlos_watchdog_triggered, &avlos_watchdog_timeout };
uint32_t avlos_proto_hash = 3526126264;

uint32_t _avlos_get_proto_hash(void)
{
Expand Down
2 changes: 1 addition & 1 deletion firmware/src/can/can_endpoints.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ typedef enum
ENCODER_TYPE_HALL = 1
} encoder_type_options;

extern uint32_t avlos_proto_hash;
static const uint32_t avlos_proto_hash = 3526126264;
extern uint8_t (*avlos_endpoints[79])(uint8_t * buffer, uint8_t * buffer_len, Avlos_Command cmd);
extern uint32_t _avlos_get_proto_hash(void);

Expand Down
253 changes: 1 addition & 252 deletions firmware/src/can/can_func.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ uint8_t data_length;
uint32_t rx_id;
bool rtr;
uint32_t can_ep_id;
uint32_t can_seq_id;
uint32_t can_frame_hash;

// * The function "can_io_config" is part of the Tinymovr-Firmware distribution
// * (https://github.com/yconst/tinymovr-firmware).
Expand Down Expand Up @@ -169,256 +169,5 @@ void can_baud(CAN_BAUD_TYPE baud)
}
}

TM_RAMFUNC void can_process_standard(void)
{
uint32_t buffer = PAC55XX_CAN->RXBUF; // read RX buffer, RX buffer bit order same as TX buffer

data_length = buffer & 0x0F;
rx_id = ((buffer & 0xE00000) >> 21) | ((buffer & 0xFF00) >> 5);

can_ep_id = rx_id & 0x3F;
rtr = ((buffer >> 6) & 0x1) == 0x1;
rx_data[0] = buffer >> 24; // data0
if (data_length > 1u)
{
buffer = PAC55XX_CAN->RXBUF; // buffer contains data1..data4
rx_data[1] = buffer;
rx_data[2] = buffer >> 8;
rx_data[3] = buffer >> 16;
rx_data[4] = buffer >> 24;
if (data_length > 5u)
{
buffer = PAC55XX_CAN->RXBUF; // buffer contains data7..data5
rx_data[5] = buffer;
rx_data[6] = buffer >> 8;
rx_data[7] = buffer >> 16;
}
}
}

// * The function "can_process_extended" is part of the Tinymovr-Firmware distribution
// * (https://github.com/yconst/tinymovr-firmware).
// * Copyright (c) 2022 Ioannis Chatzikonstantinou.
// *
// * 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, version 3.
// *
// * 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/>.

TM_RAMFUNC void can_process_extended(void)
{
uint32_t buffer = PAC55XX_CAN->RXBUF; // read RX buffer, RX buffer bit order same as TX buffer

data_length = buffer & 0x0F;
rtr = ((buffer >> 6) & 0x1) == 0x1;
rx_id = ((buffer & 0xFF000000) >> 19) | ((buffer & 0x00FF0000) >> 3) | ((buffer & 0x0000FF00) << 13);

buffer = PAC55XX_CAN->RXBUF;

rx_id |= (buffer & 0xFF) >> 3;

ids_from_arbitration(rx_id, &can_ep_id, &can_seq_id);

rx_data[0] = (buffer >> 8) & 0xFF; // data0
rx_data[1] = (buffer >> 16) & 0xFF; // data1
rx_data[2] = (buffer >> 24) & 0xFF; // data2
if (data_length > 3u)
{
buffer = PAC55XX_CAN->RXBUF; // buffer contains data3..data6
rx_data[3] = buffer & 0xFF;
rx_data[4] = (buffer >> 8) & 0xFF;
rx_data[5] = (buffer >> 16) & 0xFF;
rx_data[6] = (buffer >> 24) & 0xFF;
if (data_length > 7u)
{
buffer = PAC55XX_CAN->RXBUF; // buffer contains data7
rx_data[7] = buffer & 0xFF;
}
}
}

TM_RAMFUNC void can_transmit_standard(uint8_t dataLen, uint16_t id, const uint8_t * data)
{
while (PAC55XX_CAN->SR.TBS == 0) {}; // wait for TX buffer free
PAC55XX_CAN->TXBUF = (dataLen << 0) | // DLC - Data Length Code
(0u << 6) | // RTR = 0 Data Frame
(0u << 7) | // FF - Format Frame; 0=Std Frame
((id>>3 & 0xFF) << 8) | // ID 10:3
((id&0x07u) << 21) | // ID 2:0
(data[0] << 24); // Data 0

if (dataLen > 1u)
{
PAC55XX_CAN->TXBUF = (data[1] << 0) | // Data 1
(data[2] << 8) | // Data 2
(data[3] << 16) | // Data 3
(data[4] << 24); // Data 4
}
if (dataLen > 5u)
{
PAC55XX_CAN->TXBUF = (data[5] << 0) | // Data 5
(data[6] << 8) | // Data 6
(data[7] << 16); // Data 7

}

PAC55XX_CAN->CMR.TR = 1; // Request transmit
}

// * The function "can_transmit_extended" is part of the Tinymovr-Firmware distribution
// * (https://github.com/yconst/tinymovr-firmware).
// * Copyright (c) 2022 Ioannis Chatzikonstantinou.
// *
// * 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, version 3.
// *
// * 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/>.

TM_RAMFUNC void can_transmit_extended(uint8_t dataLen, uint32_t id, const uint8_t * data)
{
while (PAC55XX_CAN->SR.TBS == 0) {}; // wait for TX buffer free
PAC55XX_CAN->TXBUF = (dataLen << 0) | // DLC - Data Length Code
(0u << 6) | // RTR = 0 Data Frame
(1u << 7) | // FF - Format Frame; 1=Ext Frame
((id&0x1FE00000u) >> (21-8)) |
((id&0x001FE000u) << (16-13)) |
((id&0x00001FE0u) << (24-5));

PAC55XX_CAN->TXBUF = ((id & 0x1F) << 3) |
((data[0] & 0xFF) << 8) |
((data[1] & 0xFF) << 16) |
((data[2] & 0xFF) << 24);

if (dataLen > 3u)
{
PAC55XX_CAN->TXBUF = ((data[3] & 0xFF) << 0) | // Data 3
((data[4] & 0xFF) << 8) | // Data 4
((data[5] & 0xFF) << 16) | // Data 5
((data[6] & 0xFF) << 24); // Data 6
}
if (dataLen > 7u)
{
PAC55XX_CAN->TXBUF = ((data[7] & 0xFF) << 0); // Data 7
}

PAC55XX_CAN->CMR.TR = 1; // Request transmit
}

uint16_t CAN_BaudTypeToInt(CAN_BAUD_TYPE type)
{
uint16_t ret = 0u;
switch(type)
{
case CAN_BAUD_50KHz:
ret = 50u;
break;

case CAN_BAUD_100KHz:
ret = 100u;
break;

case CAN_BAUD_125KHz:
ret = 125u;
break;

case CAN_BAUD_200KHz:
ret = 200u;
break;

case CAN_BAUD_250KHz:
ret = 250u;
break;

case CAN_BAUD_400KHz:
ret = 400u;
break;

case CAN_BAUD_500KHz:
ret = 500u;
break;

case CAN_BAUD_800KHz:
ret = 800u;
break;

case CAN_BAUD_1000KHz:
ret = 1000u;
break;

default:
// ret already set
break;
}
return ret;
}

CAN_BAUD_TYPE CAN_IntToBaudType(uint16_t baud)
{
CAN_BAUD_TYPE ret = CAN_BAUD_250KHz;
switch(baud)
{
case 50u:
ret = CAN_BAUD_50KHz;
break;

case 100u:
ret = CAN_BAUD_100KHz;
break;

case 125u:
ret = CAN_BAUD_125KHz;
break;

case 200u:
ret = CAN_BAUD_200KHz;
break;

// 250 handled in default

case 400u:
ret = CAN_BAUD_400KHz;
break;

case 500u:
ret = CAN_BAUD_500KHz;
break;

case 800u:
ret = CAN_BAUD_800KHz;
break;

case 1000u:
ret = CAN_BAUD_1000KHz;
break;

default:
// ret already set
break;
}
return ret;
}

inline void ids_from_arbitration(uint32_t arb_id, uint32_t* ep_id, uint32_t* seq_id)
{
*ep_id = arb_id & CAN_EP_MASK;
*seq_id = (arb_id & CAN_SEQ_MASK) >> CAN_EP_SIZE;
}

inline void arbitration_from_ids(uint32_t* arb_id, uint32_t ep_id, uint32_t seq_id, uint32_t node_id)
{
*arb_id = (ep_id & CAN_EP_MASK) | ((seq_id << CAN_EP_SIZE) & CAN_SEQ_MASK) | ((node_id << (CAN_EP_SIZE + CAN_SEQ_SIZE)) & CAN_DEV_MASK);
}
Loading

0 comments on commit fdfd668

Please sign in to comment.