Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
45b7232edThis file is pinned to the selected release. Download the original to open it in your design tool.
// * This file is part of the Tinymovr-Firmware distribution
// * (https://github.com/yconst/tinymovr-firmware).
// * Copyright (c) 2020-2023 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/>.
#include <string.h>
#include <src/system/system.h>
#include <src/can/can_endpoints.h>
#include <src/sensor/sensor.h>
#include <src/sensor/hall.h>
#define AIO6789_IO_MODE 0x00
#define AIO_INPUT 0x00
void hall_make_blank_sensor(Sensor *s)
{
s->config.type = SENSOR_TYPE_HALL;
s->bits = HALL_BITS;
s->ticks = HALL_SECTORS;
s->normalization_factor = SENSOR_COMMON_RES_TICKS_FLOAT / s->ticks;
s->get_raw_angle_func = hall_get_angle;
s->update_func = hall_update;
s->reset_func = hall_reset;
s->init_func = hall_init;
s->deinit_func = hall_deinit;
s->get_errors_func = hall_get_errors;
s->is_calibrated_func = hall_sector_map_is_calibrated;
s->calibrate_func = hall_calibrate_sequence;
s->get_ss_config_func = hall_get_ss_config;
}
bool hall_init_with_defaults(Sensor *s)
{
HallSensorConfig c = {0};
return hall_init_with_config(s, &c);
}
bool hall_init_with_config(Sensor *s, const HallSensorConfig *c)
{
HallSensor *ms = (HallSensor *)s;
ms->config = *c;
return hall_init(s);
}
bool hall_init(Sensor *s)
{
HallSensor *ms = (HallSensor *)s;
ms->hw_defaults[0] = pac5xxx_tile_register_read(ADDR_CFGAIO7);
ms->hw_defaults[1] = pac5xxx_tile_register_read(ADDR_CFGAIO8);
ms->hw_defaults[2] = pac5xxx_tile_register_read(ADDR_CFGAIO9);
pac5xxx_tile_register_write(ADDR_CFGAIO7, AIO6789_IO_MODE | AIO_INPUT);
pac5xxx_tile_register_write(ADDR_CFGAIO8, AIO6789_IO_MODE | AIO_INPUT);
pac5xxx_tile_register_write(ADDR_CFGAIO9, AIO6789_IO_MODE | AIO_INPUT);
s->initialized = true;
return true;
}
void hall_deinit(Sensor *s)
{
HallSensor *ms = (HallSensor *)s;
pac5xxx_tile_register_write(ADDR_CFGAIO7, ms->hw_defaults[0]);
pac5xxx_tile_register_write(ADDR_CFGAIO8, ms->hw_defaults[1]);
pac5xxx_tile_register_write(ADDR_CFGAIO9, ms->hw_defaults[2]);
s->initialized = false;
}
void hall_reset(Sensor *s)
{
HallSensor *ms = (HallSensor *)s;
memset(ms->config.sector_map, 0, sizeof(ms->config.sector_map));
ms->config.sector_map_calibrated = false;
}
bool hall_calibrate_sequence(Sensor *s, Observer *o)
{
HallSensor *ms = (HallSensor *)s;
HallSensorConfig *c = &(ms->config);
(void)memset(c->sector_map, 0, sizeof(c->sector_map));
c->sector_map_calibrated = false;
uint8_t *sector_map = c->sector_map;
const float I_setpoint = motor_get_I_cal();
bool success = true;
// Stay a bit at starting epos
for (uint32_t i=0; i<CAL_STAY_LEN; i++)
{
set_epos_and_wait(0, I_setpoint);
}
const uint8_t init_sector = hall_get_sector(s);
uint8_t current_sector = init_sector;
uint8_t last_sector = init_sector;
uint8_t sector_pos = 0;
const float increment = TWOPI / CAL_DIR_LEN;
float angle = 0;
sector_map[current_sector] = sector_pos;
// Move to the 2nd sector
while ((current_sector == init_sector) && (angle < TWOPI / HALL_SECTORS))
{
set_epos_and_wait(angle, I_setpoint);
angle += increment;
current_sector = hall_get_sector(s);
}
// Save the rest of the sectors
while ((current_sector != init_sector) && (angle < TWOPI))
{
if (current_sector != last_sector)
{
last_sector = current_sector;
sector_pos++;
if (sector_pos >= HALL_SECTORS)
{
success = false;
break;
}
sector_map[current_sector] = sector_pos;
}
set_epos_and_wait(angle, I_setpoint);
angle += increment;
current_sector = hall_get_sector(s);
}
gate_driver_set_duty_cycle(&three_phase_zero);
// Check that the number of sectors discovered is the same as expected
if (sector_pos != HALL_SECTORS - 1)
{
success = false;
}
if (success)
{
c->sector_map_calibrated = true;
}
else
{
ms->errors |= SENSORS_SETUP_HALL_ERRORS_CALIBRATION_FAILED;
}
return success;
}
void hall_get_ss_config(Sensor *s, void* buffer)
{
const HallSensor *ss = ((const HallSensor *)s);
memcpy(buffer, &(ss->config), sizeof(ss->config));
}