mirror of
https://github.com/DCC-EX/CommandStation-EX.git
synced 2025-04-20 20:21:18 +02:00
Sync DC mode tracks - Nucleo-F4
This commit is contained in:
parent
83a5c52a0d
commit
e76cdd7c06
@ -1,6 +1,7 @@
|
||||
/*
|
||||
* © 2023 Neil McKechnie
|
||||
* © 2022-2024 Paul M. Antoine
|
||||
* © 2025 Herb Morton
|
||||
* © 2021 Mike S
|
||||
* © 2021, 2023 Harald Barth
|
||||
* © 2021 Fred Decker
|
||||
@ -36,6 +37,21 @@
|
||||
#include "DIAG.h"
|
||||
#include <wiring_private.h>
|
||||
|
||||
// DC mode timers enable the PWM signal on select pins.
|
||||
// Code added to sync timers which have the same frequency.
|
||||
// Function prototypes
|
||||
void refreshDCmodeTimers();
|
||||
void resetCounterDCmodeTimers();
|
||||
|
||||
HardwareTimer *Timer1 = new HardwareTimer(TIM1);
|
||||
HardwareTimer *Timer2 = new HardwareTimer(TIM2);
|
||||
HardwareTimer *Timer3 = new HardwareTimer(TIM3);
|
||||
HardwareTimer *Timer4 = new HardwareTimer(TIM4);
|
||||
HardwareTimer *Timer9 = new HardwareTimer(TIM9);
|
||||
#if defined(TIM13)
|
||||
HardwareTimer *Timer13 = new HardwareTimer(TIM13);
|
||||
#endif
|
||||
|
||||
#if defined(ARDUINO_NUCLEO_F401RE)
|
||||
// Nucleo-64 boards don't have additional serial ports defined by default
|
||||
// Serial1 is available on the F401RE, but not hugely convenient.
|
||||
@ -290,7 +306,7 @@ void DCCTimer::DCCEXanalogWriteFrequency(uint8_t pin, uint32_t f) {
|
||||
else if (f >= 3)
|
||||
DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, 16000);
|
||||
else if (f >= 2)
|
||||
DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, 3400);
|
||||
DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, 3600);
|
||||
else if (f == 1)
|
||||
DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, 480);
|
||||
else
|
||||
@ -328,7 +344,8 @@ void DCCTimer::DCCEXanalogWriteFrequencyInternal(uint8_t pin, uint32_t frequency
|
||||
if (pin_timer[pin] != NULL)
|
||||
{
|
||||
pin_timer[pin]->setPWM(pin_channel[pin], pin, frequency, 0); // set frequency in Hertz, 0% dutycycle
|
||||
DIAG(F("DCCEXanalogWriteFrequency::Pin %d on Timer Channel %d, frequency %d"), pin, pin_channel[pin], frequency);
|
||||
DIAG(F("DCCEXanalogWriteFrequency::Pin %d on Timer %d Channel %d, frequency %d"), pin, pin_timer[pin], pin_channel[pin], frequency);
|
||||
resetCounterDCmodeTimers();
|
||||
}
|
||||
else
|
||||
DIAG(F("DCCEXanalogWriteFrequency::failed to allocate HardwareTimer instance!"));
|
||||
@ -341,6 +358,7 @@ void DCCTimer::DCCEXanalogWriteFrequencyInternal(uint8_t pin, uint32_t frequency
|
||||
pinmap_pinout(digitalPinToPinName(pin), PinMap_TIM); // ensure the pin has been configured!
|
||||
pin_timer[pin]->setOverflow(frequency, HERTZ_FORMAT); // Just change the frequency if it's already running!
|
||||
DIAG(F("DCCEXanalogWriteFrequency::setting frequency to %d"), frequency);
|
||||
resetCounterDCmodeTimers();
|
||||
}
|
||||
}
|
||||
channel_frequency[pin] = frequency;
|
||||
@ -365,6 +383,8 @@ void DCCTimer::DCCEXanalogWrite(uint8_t pin, int value, bool invert) {
|
||||
pin_timer[pin]->setCaptureCompare(pin_channel[pin], duty_cycle, PERCENT_COMPARE_FORMAT); // DCC_EX_PWM_FREQ Hertz, duty_cycle% dutycycle
|
||||
DIAG(F("DCCEXanalogWrite::Pin %d, value %d, duty cycle %d"), pin, value, duty_cycle);
|
||||
// }
|
||||
refreshDCmodeTimers();
|
||||
resetCounterDCmodeTimers();
|
||||
}
|
||||
else
|
||||
DIAG(F("DCCEXanalogWrite::Pin %d is not configured for PWM!"), pin);
|
||||
@ -659,4 +679,35 @@ void ADCee::begin() {
|
||||
#endif
|
||||
interrupts();
|
||||
}
|
||||
|
||||
// NOTE: additional testing is needed to check the DCC signal
|
||||
// where the DCC signal pin is a pwm pin on timers 1, 2, 3, 4, 9, 13
|
||||
// or the brake pin is defined on a different timer.
|
||||
// -- example: F411RE/F446RE - pin 10 on stacked EX8874
|
||||
// lines added to sync timers --
|
||||
// not exact sync, but timers with the same frequency should be in sync
|
||||
void refreshDCmodeTimers() {
|
||||
Timer1->refresh();
|
||||
Timer2->refresh();
|
||||
Timer3->refresh();
|
||||
Timer4->refresh();
|
||||
Timer9->refresh();
|
||||
#if defined(TIM13)
|
||||
Timer13->refresh();
|
||||
#endif
|
||||
}
|
||||
|
||||
// Function to synchronize timers - called every time there is powerON commmand for any DC track
|
||||
void resetCounterDCmodeTimers() {
|
||||
// Reset the counter for all DC mode timers
|
||||
TIM1->CNT = 0;
|
||||
TIM2->CNT = 0;
|
||||
TIM3->CNT = 0;
|
||||
TIM4->CNT = 0;
|
||||
TIM9->CNT = 0;
|
||||
#if defined(TIM13)
|
||||
TIM13->CNT = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -371,8 +371,8 @@ void MotorDriver::setDCSignal(byte speedcode, uint8_t frequency /*default =0*/)
|
||||
}
|
||||
#endif
|
||||
//DIAG(F("Brake pin %d value %d freqency %d"), brakePin, brake, f);
|
||||
DCCTimer::DCCEXanalogWrite(brakePin, brake, invertBrake);
|
||||
DCCTimer::DCCEXanalogWriteFrequency(brakePin, f); // set DC PWM frequency
|
||||
DCCTimer::DCCEXanalogWrite(brakePin, brake, invertBrake); // line swapped to set frequency first
|
||||
#else // all AVR here
|
||||
DCCTimer::DCCEXanalogWriteFrequency(brakePin, frequency); // frequency steps
|
||||
analogWrite(brakePin, invertBrake ? 255-brake : brake);
|
||||
|
@ -2,7 +2,7 @@
|
||||
* © 2022-2025 Chris Harlow
|
||||
* © 2022-2024 Harald Barth
|
||||
* © 2023-2024 Paul M. Antoine
|
||||
* © 2024 Herb Morton
|
||||
* © 2024-2025 Herb Morton
|
||||
* © 2023 Colin Murdoch
|
||||
* All rights reserved.
|
||||
*
|
||||
@ -557,6 +557,20 @@ void TrackManager::setTrackPower(TRACK_MODE trackmodeToMatch, POWERMODE powermod
|
||||
}
|
||||
if (didChange)
|
||||
CommandDistributor::broadcastPower();
|
||||
|
||||
// re-initialize DC mode timer settings following powerON
|
||||
if (powermode == POWERMODE::ON) {
|
||||
#ifdef ARDUINO_ARCH_STM32
|
||||
// for (byte i=0;i<=lastTrack;i++) {
|
||||
// setTrackPowerF439ZI(i);
|
||||
// }
|
||||
// repeated in case the <F29..31 was set on a later track than power
|
||||
// Note: this retains power but prevents speed doubling
|
||||
for (byte i=0;i<lastTrack;i++) {
|
||||
setTrackPowerF439ZI(i);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// Set track power for this track, inependent of mode
|
||||
@ -587,6 +601,20 @@ void TrackManager::setTrackPower(POWERMODE powermode, byte t) {
|
||||
driver->setPower(powermode);
|
||||
if (oldpower != driver->getPower())
|
||||
CommandDistributor::broadcastPower();
|
||||
|
||||
// re-initialize DC mode timer settings following powerON
|
||||
if (powermode == POWERMODE::ON) {
|
||||
#ifdef ARDUINO_ARCH_STM32
|
||||
for (byte i=0;i<=lastTrack;i++) {
|
||||
setTrackPowerF439ZI(i);
|
||||
}
|
||||
// repeated in case the <F29..31 was set on a later track than power
|
||||
// Note: this retains power but prevents speed doubling
|
||||
for (byte i=0;i<lastTrack;i++) {
|
||||
setTrackPowerF439ZI(i);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// returns state of the one and only prog track
|
||||
@ -710,3 +738,38 @@ TRACK_MODE TrackManager::getMode(byte t) {
|
||||
int16_t TrackManager::returnDCAddr(byte t) {
|
||||
return (trackDCAddr[t]);
|
||||
}
|
||||
|
||||
// Set track power for EACH track, independent of mode
|
||||
// This updates the settings so that speed is correct
|
||||
// following a frequency change - DC mode
|
||||
void TrackManager::setTrackPowerF439ZI(byte t) {
|
||||
MotorDriver *driver=track[t];
|
||||
if (driver == NULL) { // track is not defined at all
|
||||
// DIAG(F("Error: Track %c does not exist"), t+'A');
|
||||
return;
|
||||
}
|
||||
TRACK_MODE trackmode = driver->getMode();
|
||||
POWERMODE powermode = driver->getPower(); // line added to enable processing for DC mode tracks
|
||||
POWERMODE oldpower = driver->getPower();
|
||||
//if (trackmode & TRACK_MODE_NONE) {
|
||||
// driver->setBrake(true); // Track is unused. Brake is good to have.
|
||||
// powermode = POWERMODE::OFF; // Track is unused. Force it to OFF
|
||||
//} else
|
||||
if (trackmode & TRACK_MODE_DC) { // includes inverted DC (called DCX)
|
||||
if (powermode == POWERMODE::ON) {
|
||||
driver->setBrake(true); // DC starts with brake on
|
||||
applyDCSpeed(t); // speed match DCC throttles
|
||||
}
|
||||
}
|
||||
//else /* MAIN PROG EXT BOOST */ {
|
||||
// if (powermode == POWERMODE::ON) {
|
||||
// // toggle brake before turning power on - resets overcurrent error
|
||||
// // on the Pololu board if brake is wired to ^D2.
|
||||
// driver->setBrake(true);
|
||||
// driver->setBrake(false); // DCC runs with brake off
|
||||
// }
|
||||
//}
|
||||
driver->setPower(powermode);
|
||||
if (oldpower != driver->getPower())
|
||||
CommandDistributor::broadcastPower();
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
/*
|
||||
* © 2022 Chris Harlow
|
||||
* © 2022-2024 Harald Barth
|
||||
* © 2025 Herb Morton
|
||||
* © 2023 Colin Murdoch
|
||||
*
|
||||
* All rights reserved.
|
||||
@ -69,6 +70,7 @@ class TrackManager {
|
||||
static void setTrackPower(TRACK_MODE trackmode, POWERMODE powermode);
|
||||
static void setMainPower(POWERMODE mode) {setTrackPower(TRACK_MODE_MAIN, mode);}
|
||||
static void setProgPower(POWERMODE mode) {setTrackPower(TRACK_MODE_PROG, mode);}
|
||||
static void setTrackPowerF439ZI(byte t);
|
||||
|
||||
static const int16_t MAX_TRACKS=8;
|
||||
static bool setTrackMode(byte track, TRACK_MODE mode, int16_t DCaddr=0);
|
||||
|
@ -3,7 +3,8 @@
|
||||
|
||||
#include "StringFormatter.h"
|
||||
|
||||
#define VERSION "5.5.21"
|
||||
#define VERSION "5.5.22"
|
||||
// 5.5.22 - Sync DC mode tracks - Nucleo-F4
|
||||
// 5.5.21 - Backed out the broken merge with frequency change and
|
||||
// 5.5.20 - EXRAIL SET/RESET assert fix
|
||||
// 5.5.19 - Railcom change to use RailcomCollector device
|
||||
|
Loading…
x
Reference in New Issue
Block a user