improved formatting and fixed clangd includes

This commit is contained in:
2025-02-21 10:31:36 +01:00
parent 26e9075871
commit b3c5bd7834
12 changed files with 723 additions and 393 deletions

135
.clang-format Normal file
View File

@@ -0,0 +1,135 @@
---
Language: Cpp
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AlignConsecutiveMacros: false
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Right
AlignOperands: true
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: false
AllowAllConstructorInitializersOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: None
AllowShortLambdasOnASingleLine: All
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: false
BinPackParameters: false
BraceWrapping:
AfterCaseLabel: true
AfterClass: true
AfterControlStatement: true
AfterEnum: true
AfterFunction: true
AfterNamespace: true
AfterObjCDeclaration: true
AfterStruct: true
AfterUnion: true
AfterExternBlock: true
BeforeCatch: true
BeforeElse: true
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Custom
BreakBeforeInheritanceComma: false

11
.clang-tidy Normal file
View File

@@ -0,0 +1,11 @@
---
Checks: 'clang-analyzer-*,bugprone-*,readability-*,cppcoreguidelines-*,-readability-avoid-const-params-in-decls,-cppcoreguidelines-avoid-non-const-global-variables,-bugprone-easily-swappable-parameters,-altera-*,-readability-uppercase-literal-suffix,-bugprone-branch-clone,-cppcoreguidelines-pro-*,-readability-function-cognitive-complexity,-cppcoreguidelines-avoid-magic-numbers,-clang-analyzer-security.insecureAPI.*'
WarningsAsErrors: ''
HeaderFilterRegex: ''
CheckOptions:
- key: readability-magic-numbers.IgnoredFloatingPointValues
value: '0.0;1.0;100.0;'
- key: readability-magic-numbers.IgnoredIntegerValues
value: '0;1;2;3;4;5;6;7;8;9;255;256;65535;15;4294967295'
- key: readability-braces-around-statements.ShortStatementLines
value: '2'

5
.clangd Normal file
View File

@@ -0,0 +1,5 @@
---
CompileFlags:
Add:
- "-I/home/dennisgunia/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/avr/include/"
- "-I"

View File

@@ -1,57 +1,20 @@
{ {
"env": { "env": {
"myIncludePath": ["${workspaceFolder}/include", "${workspaceFolder}/src"], "arduino_path": "/home/dennisgunia/.arduino15/packages/arduino",
"myDefines": ["DEBUG", "MY_FEATURE=1"] "arduino_avr_include2_path": "${env:arduino_path}/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/avr/include"
}, },
"configurations": [ "configurations": [
{ {
"name": "Linux", "name": "linux-gcc-x64",
"compilerPath": "/usr/bin/avr-gcc", "compilerPath": "/usr/bin/gcc",
"compilerArgs": ["-mmcu=atmega8", "-DF_CPU=16000000UL", "-Os"], "includePath": [
"intelliSenseMode": "linux-gcc-x86", "${workspaceFolder}/**",
"includePath": ["${myIncludePath}", "/usr/include"], "~/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/avr/include"
"defines": ["${myDefines}"], ],
"cStandard": "gnu11", "defines": [],
"cppStandard": "gnu++14",
"configurationProvider": "ms-vscode.cmake-tools",
"forcedInclude": ["${workspaceFolder}/common.h"],
"compileCommands": "${workspaceFolder}/build/compile_commands.json",
"dotConfig": "${workspaceFolder}/.config",
"mergeConfigurations": true,
"customConfigurationVariables": {
"myVar": "myvalue"
},
"browse": {
"path": ["${myIncludePath}", "/usr/include", "${workspaceFolder}"],
"limitSymbolsToIncludedHeaders": true,
"databaseFilename": "${workspaceFolder}/.vscode/browse.vc.db"
}
},
{
"name": "Mac",
"compilerPath": "/usr/bin/clang",
"intelliSenseMode": "macos-clang-x64",
"includePath": ["${myIncludePath}"],
"defines": ["${myDefines}"],
"cStandard": "c11", "cStandard": "c11",
"cppStandard": "c++17",
"macFrameworkPath": ["/System/Library/Frameworks", "/Library/Frameworks"],
"browse": {
"path": ["${myIncludePath}", "${workspaceFolder}"]
}
},
{
"name": "Win32",
"compilerPath": "C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.28.29333/bin/Hostx64/x64/cl.exe",
"intelliSenseMode": "windows-msvc-x64",
"includePath": ["${myIncludePath}"],
"defines": ["${myDefines}", "_WINDOWS"],
"cStandard": "c17",
"cppStandard": "c++20", "cppStandard": "c++20",
"windowsSdkVersion": "10.0.19041.0", "intelliSenseMode": "linux-gcc-x64"
"browse": {
"path": ["${myIncludePath}", "${workspaceFolder}"]
}
} }
], ],
"version": 4, "version": 4,

24
.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,24 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "C/C++ Runner: Debug Session",
"type": "cppdbg",
"request": "launch",
"args": [],
"stopAtEntry": false,
"externalConsole": false,
"cwd": "/nas_projects/current/SplitFlapController/software/firmware_module/module_rev0/src",
"program": "/nas_projects/current/SplitFlapController/software/firmware_module/module_rev0/src/build/Debug/outDebug",
"MIMode": "gdb",
"miDebuggerPath": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
]
}
]
}

62
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,62 @@
{
"C_Cpp_Runner.cCompilerPath": "gcc",
"C_Cpp_Runner.cppCompilerPath": "g++",
"C_Cpp_Runner.debuggerPath": "gdb",
"C_Cpp_Runner.cStandard": "c11",
"C_Cpp_Runner.cppStandard": "c++20",
"C_Cpp_Runner.msvcBatchPath": "",
"C_Cpp_Runner.useMsvc": false,
"C_Cpp_Runner.warnings": [
"-Wall",
"-Wextra",
"-Wpedantic",
"-Wshadow",
"-Wformat=2",
"-Wcast-align",
"-Wconversion",
"-Wsign-conversion",
"-Wnull-dereference"
],
"C_Cpp_Runner.msvcWarnings": [
"/W4",
"/permissive-",
"/w14242",
"/w14287",
"/w14296",
"/w14311",
"/w14826",
"/w44062",
"/w44242",
"/w14905",
"/w14906",
"/w14263",
"/w44265",
"/w14928"
],
"C_Cpp_Runner.enableWarnings": true,
"C_Cpp_Runner.warningsAsError": false,
"C_Cpp_Runner.compilerArgs": [],
"C_Cpp_Runner.linkerArgs": [],
"C_Cpp_Runner.includePaths": [
"~/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/avr/include"
],
"C_Cpp_Runner.includeSearch": [
"*",
"**/*",
"~/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/avr/include/**"
],
"C_Cpp_Runner.excludeSearch": [
"**/build",
"**/build/**",
"**/.*",
"**/.*/**",
"**/.vscode",
"**/.vscode/**"
],
"C_Cpp_Runner.useAddressSanitizer": false,
"C_Cpp_Runner.useUndefinedSanitizer": false,
"C_Cpp_Runner.useLeakSanitizer": false,
"C_Cpp_Runner.showCompilationTime": false,
"C_Cpp_Runner.useLinkTimeOptimization": false,
"C_Cpp_Runner.msvcSecureNoWarnings": false
}

View File

@@ -12,7 +12,7 @@
#include <util/delay.h> #include <util/delay.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <avr/iom8.h>
// I/O Pin definition // I/O Pin definition
@@ -31,3 +31,28 @@
#define CONF_ADDR_OKAY 0x0004 #define CONF_ADDR_OKAY 0x0004
#define CONF_ADDR_ADDR 0x0000 #define CONF_ADDR_ADDR 0x0000
#define CONF_ADDR_OFFSET 0x0002 #define CONF_ADDR_OFFSET 0x0002
// Protocol definitions
#define PROTO_MAXPKGLEN 64 // maximum size of package in bytes
// Commands
#define CMDB_SETVAL (uint8_t)0x10
#define CMDB_SETVALR (uint8_t)0x11
#define CMDB_EEPROMR (uint8_t)0xF0
#define CMDB_EEPROMW (uint8_t)0xF1
#define CMDB_GSTS (uint8_t)0xF8
#define CMDB_PING (uint8_t)0xFE
#define CMDB_RESET (uint8_t)0x30
#define CMDB_PWRON (uint8_t)0x21
#define CMDB_RPWROFF (uint8_t)0x20
// Reply
#define CMDR_ERR_INVALID 0xEE
#define CMDR_ACK 0xAA
#define CMDR_PING 0xFF
// Utility definitions
#define SHIFT_0B 0
#define SHIFT_1B 8
#define SHIFT_2B 16
#define SHIFT_3B 24

View File

@@ -10,10 +10,12 @@
#include "mctrl.h" #include "mctrl.h"
#include "rcount.h" #include "rcount.h"
#include "rs485.h" #include "rs485.h"
uint16_t address = 0x0000;
int16_t calib_offset = 0x0000;
void eeprom_write_c(uint16_t address, uint8_t data) { uint16_t address = 0x0000;
uint16_t calib_offset = 0x0000;
void eeprom_write_c(uint16_t address, uint8_t data)
{
// disable interrupt // disable interrupt
cli(); cli();
while (EECR & (1 << EEWE)) while (EECR & (1 << EEWE))
@@ -25,7 +27,8 @@ void eeprom_write_c(uint16_t address, uint8_t data) {
sei(); sei();
} }
uint8_t eeprom_read_c(uint16_t address) { uint8_t eeprom_read_c(uint16_t address)
{
while (EECR & (1 << EEWE)) while (EECR & (1 << EEWE))
; // wait until previous write is done ; // wait until previous write is done
EEAR = address; EEAR = address;
@@ -33,16 +36,20 @@ uint8_t eeprom_read_c(uint16_t address) {
return EEDR; return EEDR;
} }
void initialSetup() { void initialSetup()
{
wdt_disable(); wdt_disable();
if (eeprom_read_c(CONF_ADDR_OKAY) == CONF_CONST_OKAY) { if (eeprom_read_c(CONF_ADDR_OKAY) == CONF_CONST_OKAY)
{
uint8_t addrL = eeprom_read_c(CONF_ADDR_ADDR); uint8_t addrL = eeprom_read_c(CONF_ADDR_ADDR);
uint8_t addrH = eeprom_read_c(CONF_ADDR_ADDR + 1); uint8_t addrH = eeprom_read_c(CONF_ADDR_ADDR + 1);
address = addrL | (addrH << 8); address = addrL | (addrH << 8);
uint8_t offsetL = eeprom_read_c(CONF_ADDR_OFFSET); uint8_t offsetL = eeprom_read_c(CONF_ADDR_OFFSET);
uint8_t offsetH = eeprom_read_c(CONF_ADDR_OFFSET + 1); uint8_t offsetH = eeprom_read_c(CONF_ADDR_OFFSET + 1);
calib_offset = offsetL | (offsetH << 8); calib_offset = (offsetL | (offsetH << 8));
} else { }
else
{
eeprom_write_c(CONF_ADDR_ADDR, (uint8_t)0x00); eeprom_write_c(CONF_ADDR_ADDR, (uint8_t)0x00);
eeprom_write_c(CONF_ADDR_ADDR + 1, (uint8_t)0x00); eeprom_write_c(CONF_ADDR_ADDR + 1, (uint8_t)0x00);
eeprom_write_c(CONF_ADDR_OFFSET, (uint8_t)0x00); eeprom_write_c(CONF_ADDR_OFFSET, (uint8_t)0x00);
@@ -51,46 +58,57 @@ void initialSetup() {
} }
} }
void readCommand() { void readCommand()
char *payload = malloc(64); {
char *payload = malloc(PROTO_MAXPKGLEN);
uint8_t payload_len = sfbus_recv_frame(address, payload); uint8_t payload_len = sfbus_recv_frame(address, payload);
if (payload_len > 0) { if (payload_len > 0)
{
// read command byte // read command byte
uint8_t opcode = *payload; uint8_t opcode = *payload;
// parse commands // parse commands
if (opcode == (uint8_t)0x10) { if (opcode == CMDB_SETVAL)
{
// 0x1O = Set Digit // 0x1O = Set Digit
uint8_t targetDigit = *(payload + 1); uint8_t targetDigit = *(payload + 1);
mctrl_set(targetDigit, 0); mctrl_set(targetDigit, 0);
} else if (opcode == (uint8_t)0x11) { }
else if (opcode == CMDB_SETVALR)
{
// 0x11 = Set Digit (full rotation) // 0x11 = Set Digit (full rotation)
uint8_t targetDigit = *(payload + 1); uint8_t targetDigit = *(payload + 1);
mctrl_set(targetDigit, 1); mctrl_set(targetDigit, 1);
} else if (opcode == (uint8_t)0xF0) { }
else if (opcode == CMDB_EEPROMR)
{
// 0xFO = READ EEPROM // 0xFO = READ EEPROM
uint8_t bytes = 5; uint8_t bytes = 5;
char *msg = malloc(bytes + 1); char *msg = malloc(bytes + 1);
*msg = 0xAA; *msg = CMDR_ACK;
for (uint16_t i = 1; i < (uint16_t)bytes + 1; i++) { for (uint16_t i = 1; i < (uint16_t)bytes + 1; i++)
*(msg + i) = eeprom_read_c(i - 1); {
*(msg + i) = (char)eeprom_read_c(i - 1);
} }
_delay_ms(2); _delay_ms(2);
sfbus_send_frame(0xFFFF, msg, bytes + 1); sfbus_send_frame(0xFFFF, msg, bytes + 1);
free(msg); free(msg);
}
} else if (opcode == (uint8_t)0xF1) { else if (opcode == CMDB_EEPROMW)
{
// 0xF1 = WRITE EEPROM // 0xF1 = WRITE EEPROM
eeprom_write_c(CONF_ADDR_OKAY, (char)0xFF); eeprom_write_c(CONF_ADDR_OKAY, (char)0xFF);
for (uint16_t i = 0; i < 4; i++) { for (uint16_t i = 0; i < 4; i++)
{
eeprom_write_c(i, *(payload + 1 + i)); eeprom_write_c(i, *(payload + 1 + i));
} }
eeprom_write_c(CONF_ADDR_OKAY, CONF_CONST_OKAY); eeprom_write_c(CONF_ADDR_OKAY, CONF_CONST_OKAY);
// respond with readout // respond with readout
uint8_t bytes = 5; uint8_t bytes = 5;
char *msg = malloc(bytes + 1); char *msg = malloc(bytes + 1);
*msg = 0xAA; *msg = CMDR_ACK;
for (uint16_t i = 1; i < (uint16_t)bytes + 1; i++) { for (uint16_t i = 1; i < (uint16_t)bytes + 1; i++)
*(msg + i) = eeprom_read_c(i - 1); {
*(msg + i) = (char)eeprom_read_c(i - 1);
} }
_delay_ms(2); _delay_ms(2);
sfbus_send_frame(0xFFFF, msg, bytes + 1); sfbus_send_frame(0xFFFF, msg, bytes + 1);
@@ -98,42 +116,52 @@ void readCommand() {
// now use new addr // now use new addr
uint8_t addrL = eeprom_read_c(CONF_ADDR_ADDR); uint8_t addrL = eeprom_read_c(CONF_ADDR_ADDR);
uint8_t addrH = eeprom_read_c(CONF_ADDR_ADDR + 1); uint8_t addrH = eeprom_read_c(CONF_ADDR_ADDR + 1);
address = addrL | (addrH << 8); address = addrL | (addrH << SHIFT_1B);
} else if (opcode == (uint8_t)0xF8) { }
// 0xF8 = Get Status else if (opcode == CMDB_GSTS)
{
char *msg = malloc(7); char *msg = malloc(7);
*msg = getSts(); *msg = (char)getSts();
uint16_t voltage = getVoltage(); uint16_t voltage = getVoltage();
*(msg + 2) = (voltage >> 0) & 0xFF; *(msg + 2) = (char)((voltage >> SHIFT_0B) & 0xFF);
*(msg + 1) = (voltage >> 8) & 0xFF; *(msg + 1) = (char)((voltage >> SHIFT_1B) & 0xFF);
uint32_t counter = rc_getCounter(); uint32_t counter = rc_getCounter();
*(msg + 6) = (counter >> 0) & 0xFF; *(msg + 6) = (char)((counter >> SHIFT_0B) & 0xFF);
*(msg + 5) = (counter >> 8) & 0xFF; *(msg + 5) = (char)((counter >> SHIFT_1B) & 0xFF);
*(msg + 4) = (counter >> 16) & 0xFF; *(msg + 4) = (char)((counter >> SHIFT_2B) & 0xFF);
*(msg + 3) = (counter >> 24) & 0xFF; *(msg + 3) = (char)((counter >> SHIFT_3B) & 0xFF);
_delay_ms(2); _delay_ms(2);
sfbus_send_frame(0xFFFF, msg, 7); sfbus_send_frame(0xFFFF, msg, 7);
free(msg); free(msg);
} else if (opcode == (uint8_t)0xFE) { }
// 0xFE = PING else if (opcode == CMDB_PING)
char msg = 0xFF; {
char msg = (char)CMDR_PING;
_delay_ms(2); _delay_ms(2);
sfbus_send_frame(0xFFFF, &msg, 1); sfbus_send_frame(0xFFFF, &msg, 1);
} else if ((opcode & (uint8_t)0xFE) == (uint8_t)0x20) { }
// 0x20 = poweroff; 0x21 is poweron else if (opcode == CMDB_RPWROFF)
uint8_t state = opcode & (uint8_t)0x01; {
mctrl_power(state); mctrl_power(0);
}
} else if (opcode == (uint8_t)0x30) { else if (opcode == CMDB_PWRON)
// 0x30 = reset {
do { mctrl_power(1);
}
else if (opcode == CMDB_RESET)
{
do
{
wdt_enable(WDTO_15MS); wdt_enable(WDTO_15MS);
for (;;) { for (;;)
{
} }
} while (0); } while (0);
} else { }
else
{
// invalid opcode // invalid opcode
char msg = 0xEE; char msg = CMDR_ERR_INVALID;
_delay_ms(2); _delay_ms(2);
sfbus_send_frame(0xFFFF, &msg, 1); sfbus_send_frame(0xFFFF, &msg, 1);
} }
@@ -141,12 +169,14 @@ void readCommand() {
free(payload); free(payload);
} }
int main() { int main()
{
initialSetup(); initialSetup();
rs485_init(); rs485_init();
mctrl_init(); mctrl_init();
while (1 == 1) { while (1 == 1)
{
readCommand(); readCommand();
} }
} }

View File

@@ -20,7 +20,7 @@ uint8_t motor_steps[4] = {
uint8_t step_index = 0; // cuurent index in motor_steps uint8_t step_index = 0; // cuurent index in motor_steps
uint8_t target_flap = 0; // target flap uint8_t target_flap = 0; // target flap
uint16_t absolute_pos = 0; // absolute position in steps uint16_t absolute_pos = 0; // absolute position in steps
uint16_t rel_offset = 1400; // offset of '0' flap relative to home uint16_t rel_offset = STEPS_OFFSET; // offset of '0' flap relative to home
uint16_t steps_since_home = 0; // steps since last home signal uint16_t steps_since_home = 0; // steps since last home signal
// homing util variables // homing util variables
@@ -48,7 +48,8 @@ uint8_t currentFaultReadings = 0; // ticks with faulty readings (too many will
// trip pwrdwn and sts_flag_fuse) // trip pwrdwn and sts_flag_fuse)
// initialize motor controller // initialize motor controller
void mctrl_init() { void mctrl_init()
{
DDRC = 0x0F; // set all pins as outputs DDRC = 0x0F; // set all pins as outputs
PORTC = 0x00; // set all to LOW PORTC = 0x00; // set all to LOW
@@ -57,42 +58,43 @@ void mctrl_init() {
// setup adc // setup adc
ADMUX = 0x07; // Aref, ADC7 ADMUX = 0x07; // Aref, ADC7
ADCSRA = ADCSRA = (1 << ADEN) | (1 << ADSC) | (1 << ADPS1); // Enable ADC, Start first
(1 << ADEN) | (1 << ADSC) | (1 << ADPS1); // Enable ADC, Start first
// reading No frerunning, 8MHz // reading No frerunning, 8MHz
while ((ADCSRA & (1 << ADSC)) > 0) while ((ADCSRA & (1 << ADSC)) > 0)
; // wait until first reading is complete, {
};
// wait until first reading is complete,
// to avoid error flag on first tick! // to avoid error flag on first tick!
// setup timer for ISR // setup timer for ISR
TCCR1A = 0; TCCR1A = 0;
TCCR1B = (1 << WGM12) | (1 << CS11) | (1 << CS10); // CTC und Prescaler 64 TCCR1B = (1 << WGM12) | (1 << CS11) | (1 << CS10); // CTC und Prescaler 64
OCR1A = 480; // 8.000.000 / 64 / 1000 für 1ms OCR1A = MISR_OCR1A;
OCR1A = 580; // 8.000.000 / 64 / 1000 für 1ms
// OCR1A = 450; // 8.000.000 / 64 /
// 1000 für 1ms
TIMSK = 1 << OCIE1A; // Timerinterrupts aktivieren TIMSK = 1 << OCIE1A; // Timerinterrupts aktivieren
homing = 1; homing = 1;
delta_err = malloc(ERROR_DATASETS * sizeof(uint16_t)); delta_err = malloc(ERROR_DATASETS * sizeof(uint16_t));
_delay_ms(1000); _delay_ms(MDELAY_STARTUP);
sei(); sei();
} }
// call when critical fail. Powers down motor and sets flags // call when critical fail. Powers down motor and sets flags
void failSafe() { void failSafe()
{
sts_flag_failsafe = 1; sts_flag_failsafe = 1;
PORTC = 0x00; PORTC = 0x00;
} }
// read voltage non blocking (called every tick) // read voltage non blocking (called every tick)
void readVoltage() { void readVoltage()
{
currentVoltage = ADC; // read last measurement currentVoltage = ADC; // read last measurement
ADMUX = 0x07; // select ADC7 ADMUX = 0x07; // select ADC7
ADCSRA |= (1 << ADSC); // trigger next reading ADCSRA |= (1 << ADSC); // trigger next reading
if (currentVoltage < 128) { // if voltage is too low, fuse is probably broken if (currentVoltage < MVOLTAGE_LSTOP)
{ // if voltage is too low, fuse is probably broken
currentFaultReadings++; currentFaultReadings++;
if (currentFaultReadings > 20) { // too many fault readings trigger failSafe if (currentFaultReadings > MVOLTAGE_FAULTRD)
{ // too many fault readings trigger failSafe
sts_flag_fuse = 1; sts_flag_fuse = 1;
failSafe(); failSafe();
} }
@@ -100,60 +102,78 @@ void readVoltage() {
} }
// MAIN service routine. Called by timer 1 // MAIN service routine. Called by timer 1
ISR(TIMER1_COMPA_vect) { ISR(TIMER1_COMPA_vect)
{
readVoltage(); // read and check voltage readVoltage(); // read and check voltage
if (sts_flag_pwrdwn == 1 || sts_flag_failsafe == 1) { if (sts_flag_pwrdwn == 1 || sts_flag_failsafe == 1)
{
return; return;
} // if sts_flag_pwrdwn, STOP! } // if sts_flag_pwrdwn, STOP!
if (steps_since_home > if (steps_since_home > STEPS_PER_REV * MHOME_TOLERANCE)
STEPS_PER_REV * 1.5) { // check if home is missing for too long { // check if home is missing for too long
// home missing error. Wheel probably stuck or power fail // home missing error. Wheel probably stuck or power fail
sts_flag_noHome = 1; sts_flag_noHome = 1;
failSafe(); failSafe();
} else if (homing == 1) { // Homing procedure 1. step: move out of home }
if ((PIND & (1 << PD3)) > 0) { else if (homing == 1)
{ // Homing procedure 1. step: move out of home
if ((PIND & (1 << PD3)) > 0)
{
homing = 2; homing = 2;
} else { }
else
{
mctrl_step(); mctrl_step();
} }
} else if (homing == 2) { // Homing procedure 2. step: find magnet }
else if (homing == 2)
{ // Homing procedure 2. step: find magnet
mctrl_step(); mctrl_step();
if ((PIND & (1 << PD3)) == 0) { if ((PIND & (1 << PD3)) == 0)
{
homing = 3; homing = 3;
steps_since_home = 0; steps_since_home = 0;
absolute_pos = rel_offset; absolute_pos = rel_offset;
incrementCounter(); incrementCounter();
} }
} else if (homing == 3) { // Homing procedure 3. step: find magnet }
if (absolute_pos <= 0) { else if (homing == 3)
{ // Homing procedure 3. step: find magnet
if (absolute_pos <= 0)
{
homing = 0; homing = 0;
absolute_pos = rel_offset; absolute_pos = rel_offset;
} }
mctrl_step(); mctrl_step();
absolute_pos--; absolute_pos--;
} else { // when no failsafe is triggered and homing is done }
else
{ // when no failsafe is triggered and homing is done
// calculate target position // calculate target position
uint16_t target_pos = (target_flap * STEPS_PER_FLAP) + rel_offset; uint16_t target_pos = (target_flap * STEPS_PER_FLAP) + rel_offset;
if (target_pos >= STEPS_PER_REV) { if (target_pos >= STEPS_PER_REV)
{
target_pos -= STEPS_PER_REV; target_pos -= STEPS_PER_REV;
} }
if (absolute_pos != target_pos) { if (absolute_pos != target_pos)
{
// if target position is not reached, move motor // if target position is not reached, move motor
ticksSinceMove = 0; ticksSinceMove = 0;
mctrl_step(); mctrl_step();
absolute_pos++; absolute_pos++;
if (absolute_pos >= STEPS_PER_REV) { if (absolute_pos >= STEPS_PER_REV)
{
absolute_pos -= STEPS_PER_REV; absolute_pos -= STEPS_PER_REV;
} }
// detect home position // detect home position
if ((PIND & (1 << PD3)) == 0) { if ((PIND & (1 << PD3)) == 0)
if (lastSens == 0) { {
if (lastSens == 0)
{
// new home transition // new home transition
int16_t errorDelta = int16_t errorDelta =
(absolute_pos > (STEPS_PER_REV / 2) ? absolute_pos - STEPS_PER_REV (int16_t)(absolute_pos > (STEPS_PER_REV / 2) ? absolute_pos - STEPS_PER_REV : absolute_pos);
: absolute_pos); sts_flag_errorTooBig = (errorDelta > MHOME_ERRDELTA) || (errorDelta < -MHOME_ERRDELTA) ? 1 : 0;
sts_flag_errorTooBig =
(errorDelta > 30) || (errorDelta < -30) ? 1 : 0;
// storeErr(errorDelta); // storeErr(errorDelta);
absolute_pos = 0; absolute_pos = 0;
steps_since_home = 0; steps_since_home = 0;
@@ -161,18 +181,29 @@ ISR(TIMER1_COMPA_vect) {
incrementCounter(); incrementCounter();
} }
lastSens = 1; lastSens = 1;
} else { }
else
{
lastSens = 0; lastSens = 0;
} }
} else { // if target position is reached }
if (afterRotation < 55) { // if after rotation is set, apply it as new target else
{ // if target position is reached
if (afterRotation < (STEPS_PER_FLAP + 5))
{ // if after rotation is set, apply it as new target
target_flap = afterRotation; target_flap = afterRotation;
afterRotation = 255; afterRotation = 255;
} else if (ticksSinceMove < 2) { // if motor has not been moved }
else if (ticksSinceMove < 2)
{ // if motor has not been moved
sts_flag_busy = 0; sts_flag_busy = 0;
} else if (ticksSinceMove < 50) { // if motor has not been moved }
else if (ticksSinceMove < MPWRSVG_TICKSTOP)
{ // if motor has not been moved
ticksSinceMove++; ticksSinceMove++;
} else { // power off after 50 ticks }
else
{ // power off after 50 ticks
// PORTC = 0x00; // turn off stepper // PORTC = 0x00; // turn off stepper
} }
} }
@@ -181,70 +212,89 @@ ISR(TIMER1_COMPA_vect) {
} }
// TODO // TODO
void storeErr(int16_t error) { void storeErr(int16_t error)
{
int16_t *delta_err_tmp = malloc(ERROR_DATASETS * sizeof(uint16_t)); int16_t *delta_err_tmp = malloc(ERROR_DATASETS * sizeof(uint16_t));
memcpy(delta_err, delta_err_tmp + sizeof(uint16_t), memcpy(delta_err, delta_err_tmp + sizeof(uint16_t), ((ERROR_DATASETS - 2) * sizeof(uint16_t)));
((ERROR_DATASETS - 2) * sizeof(uint16_t)));
memcpy(&error, delta_err_tmp, sizeof(uint16_t)); memcpy(&error, delta_err_tmp, sizeof(uint16_t));
free(delta_err); free(delta_err);
delta_err = delta_err_tmp; delta_err = delta_err_tmp;
} }
// TODO // TODO
void getErr(int16_t *error) { void getErr(int16_t *error)
{
memcpy(delta_err, error, (ERROR_DATASETS * sizeof(uint16_t))); memcpy(delta_err, error, (ERROR_DATASETS * sizeof(uint16_t)));
} }
// return status flag // return status flag
uint8_t getSts() { uint8_t getSts()
{
uint8_t status = sts_flag_errorTooBig; // bit 0: delta too big uint8_t status = sts_flag_errorTooBig; // bit 0: delta too big
status |= sts_flag_noHome << 1; // bit 1: no home found status |= sts_flag_noHome << 1; // bit 1: no home found
status |= sts_flag_fuse << 2; // bit 2: fuse blown status |= sts_flag_fuse << 2; // bit 2: fuse blown
status |= sts_flag_pwrdwn << 4; // bit 4: device powered down status |= sts_flag_pwrdwn << 4; // bit 4: device powered down
status |= sts_flag_failsafe << 5; // bit 5: failsafe active status |= sts_flag_failsafe << 5; // bit 5: failsafe active
status |= sts_flag_busy << 6; // bit 6: failsafe active status |= sts_flag_busy << 6; // bit 6: failsafe active
if ((PIND & (1 << PD3)) == 0) { if ((PIND & (1 << PD3)) == 0)
{
status |= (1 << 3); status |= (1 << 3);
} }
return status; return status;
} }
// return voltage // return voltage
uint16_t getVoltage() { return currentVoltage; } uint16_t getVoltage()
{
return currentVoltage;
}
// set target flap // set target flap
void mctrl_set(uint8_t flap, uint8_t fullRotation) { void mctrl_set(uint8_t flap, uint8_t fullRotation)
{
sts_flag_busy = 1; sts_flag_busy = 1;
if (fullRotation == 0) { if (fullRotation == 0)
{
target_flap = flap; target_flap = flap;
// if (absolute_pos < STEPS_ADJ) { // if (absolute_pos < STEPS_ADJ) {
// absolute_pos += STEPS_PER_REV; // absolute_pos += STEPS_PER_REV;
// } // }
// absolute_pos -= STEPS_ADJ; // absolute_pos -= STEPS_ADJ;
} else { }
else
{
target_flap = (target_flap + (STEPS_PER_FLAP - 1)) % STEPS_PER_FLAP; target_flap = (target_flap + (STEPS_PER_FLAP - 1)) % STEPS_PER_FLAP;
afterRotation = flap; afterRotation = flap;
} }
} }
// trigger home procedure // trigger home procedure
void mctrl_home() { homing = 1; } void mctrl_home()
{
homing = 1;
}
// trigger home procedure // trigger home procedure
void mctrl_power(uint8_t state) { void mctrl_power(uint8_t state)
if (state == 0) { {
if (state == 0)
{
sts_flag_pwrdwn = 1; sts_flag_pwrdwn = 1;
PORTC = 0x00; PORTC = 0x00;
}else{ }
else
{
sts_flag_pwrdwn = 0; sts_flag_pwrdwn = 0;
PORTC = motor_steps[step_index]; PORTC = motor_steps[step_index];
} }
} }
// do stepper step (I/O) // do stepper step (I/O)
void mctrl_step() { void mctrl_step()
{
step_index++; step_index++;
steps_since_home++; steps_since_home++;
if (step_index > 3) { if (step_index > 3)
{
step_index = 0; step_index = 0;
} }
PORTC = motor_steps[step_index]; PORTC = motor_steps[step_index];

View File

@@ -12,13 +12,23 @@
#pragma once #pragma once
#define STEPS_PER_REV 2025 // steps per revolution
#define STEPS_PER_REV 2025 #define STEPS_PER_FLAP 45 // steps per flap
#define STEPS_PER_FLAP 45
#define STEPS_ADJ 0 // added per flap to compensate for motor power down #define STEPS_ADJ 0 // added per flap to compensate for motor power down
#define AMOUNTFLAPS 45 #define STEPS_OFFSET 1400 // ansolute offset between home and first flap
#define AMOUNTFLAPS 45 // amount of flaps installed in system
#define ERROR_DATASETS 8 #define ERROR_DATASETS 8 // length of error array
#define MDELAY_STARTUP 1000 // delay to wait after motor startup
#define MHOME_TOLERANCE 1.5 // tolerance for intial homing procedure
#define MHOME_ERRDELTA 30 // maximum deviation between expected home and actual home
#define MVOLTAGE_FAULTRD 20 // max. amount of fault readings before flag is set
#define MVOLTAGE_LSTOP 128 // lower voltage threshold for fuse detection
#define MPWRSVG_TICKSTOP 50 // inactive ticks before motor shutdown
#define MISR_OCR1A 580 // tick timer (defines rotation speed)
// 450, 480 also possible ?
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {

View File

@@ -9,9 +9,13 @@
#include "rcount.h" #include "rcount.h"
uint8_t rc_eeprom_write_c(uint16_t address, uint8_t data) { uint8_t rc_eeprom_write_c(uint16_t address, uint8_t data)
{
// disable interrupt // disable interrupt
if (EECR & (1 << EEWE)) { return 1; } if (EECR & (1 << EEWE))
{
return 1;
}
EEAR = address; EEAR = address;
EEDR = data; EEDR = data;
EECR |= (1 << EEMWE); // enable Master Write Enable EECR |= (1 << EEMWE); // enable Master Write Enable
@@ -19,7 +23,8 @@ uint8_t rc_eeprom_write_c(uint16_t address, uint8_t data) {
return 0; return 0;
} }
uint8_t rc_eeprom_read_c(uint16_t address) { uint8_t rc_eeprom_read_c(uint16_t address)
{
while (EECR & (1 << EEWE)) while (EECR & (1 << EEWE))
; // wait until previous write is done ; // wait until previous write is done
EEAR = address; EEAR = address;
@@ -29,26 +34,34 @@ uint8_t rc_eeprom_read_c(uint16_t address) {
uint32_t counter = (uint32_t)0xFFFFFFFF; uint32_t counter = (uint32_t)0xFFFFFFFF;
uint8_t counter_phase = 5; uint8_t counter_phase = 5;
void rc_tick() { void rc_tick()
if (counter == (uint32_t)0xFFFFFFFF) { counter = rc_getCounter(); } {
if (counter_phase < 5) { if (counter == (uint32_t)0xFFFFFFFF)
{
counter = rc_getCounter();
}
if (counter_phase < 5)
{
cli(); cli();
if (rc_eeprom_write_c(0x100 + counter_phase, ((counter >> (counter_phase * 8)) & 0xFF)) == 0) { if (rc_eeprom_write_c(0x100 + counter_phase, ((counter >> (counter_phase * 8)) & 0xFF)) == 0)
{
counter_phase++; counter_phase++;
} }
sei(); sei();
} }
} }
void incrementCounter() { void incrementCounter()
{
counter++; counter++;
counter_phase = 0; counter_phase = 0;
} }
uint32_t rc_getCounter() { uint32_t rc_getCounter()
uint32_t counter = rc_eeprom_read_c(0x100); {
counter |= ((uint32_t)rc_eeprom_read_c(0x101) << 8); uint32_t counter = rc_eeprom_read_c(RC_BASEADDR);
counter |= ((uint32_t)rc_eeprom_read_c(0x102) << 16); counter |= ((uint32_t)rc_eeprom_read_c(RC_BASEADDR + 1) << SHIFT_1B);
counter |= ((uint32_t)rc_eeprom_read_c(0x103) << 24); counter |= ((uint32_t)rc_eeprom_read_c(RC_BASEADDR + 2) << SHIFT_2B);
counter |= ((uint32_t)rc_eeprom_read_c(RC_BASEADDR + 3) << SHIFT_3B);
return counter; return counter;
} }

View File

@@ -8,6 +8,8 @@
#include "global.h" #include "global.h"
#define RC_BASEADDR 0x100
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif // __cplusplus #endif // __cplusplus