1
0
mirror of https://github.com/DCC-EX/CommandStation-EX.git synced 2025-07-30 19:03:44 +02:00

Compare commits

..

7 Commits

Author SHA1 Message Date
pmantoine
988011475c STM32 Serial port handling for WiFi 2023-06-20 08:34:27 +08:00
pmantoine
c3eb6b8d8a STM32 ADCee highestPin 2023-06-19 17:47:42 +08:00
Harald Barth
d5dad767a4 version 4.2.55 2023-06-19 00:09:27 +02:00
Harald Barth
56fcb4e5f7 Optimize DCCTimerARV.cpp 2023-06-19 00:06:04 +02:00
Harald Barth
7783837545 Back out this as it is bigger and slower
This reverts commit efb2666060.
2023-06-18 21:08:52 +02:00
Harald Barth
0266936875 STM32: Use mask as loop variable 2023-06-18 20:22:53 +02:00
Harald Barth
befb41ce98 check ADCee::init() return value 2023-06-18 20:20:58 +02:00
10 changed files with 166 additions and 207 deletions

View File

@@ -105,9 +105,14 @@ private:
// that an offset can be initialized.
class ADCee {
public:
// init does add the pin to the list of scanned pins (if this
// begin is called for any setup that must be done before
// **init** can be called. On some architectures this involves ADC
// initialisation and clock routing, sampling times etc.
static void begin();
// init adds the pin to the list of scanned pins (if this
// platform's implementation scans pins) and returns the first
// read value. It is called before the regular scan is started.
// read value (which is why it required begin to have been called first!)
// It must be called before the regular scan is started.
static int init(uint8_t pin);
// read does read the pin value from the scanned cache or directly
// if this is a platform that does not scan. fromISR is a hint if
@@ -116,19 +121,15 @@ public:
static int read(uint8_t pin, bool fromISR=false);
// returns possible max value that the ADC can return
static int16_t ADCmax();
// begin is called for any setup that must be done before
// scan can be called.
static void begin();
private:
// On platforms that scan, it is called from waveform ISR
// only on a regular basis.
static void scan();
// bit array of used pins (max 16)
static uint16_t usedpins;
static uint8_t highestPin;
// cached analog values (malloc:ed to actual number of ADC channels)
static int *analogvals;
// ids to scan (new way)
static byte *idarr;
// friend so that we can call scan() and begin()
friend class DCCWaveform;
};

View File

@@ -1,6 +1,6 @@
/*
* © 2021 Mike S
* © 2021-2022 Harald Barth
* © 2021-2023 Harald Barth
* © 2021 Fred Decker
* © 2021 Chris Harlow
* © 2021 David Cutting
@@ -29,6 +29,9 @@
#include <avr/boot.h>
#include <avr/wdt.h>
#include "DCCTimer.h"
#ifdef DEBUG_ADC
#include "TrackManager.h"
#endif
INTERRUPT_CALLBACK interruptHandler=0;
// Arduino nano, uno, mega etc
@@ -128,8 +131,8 @@ void DCCTimer::reset() {
#define NUM_ADC_INPUTS 8
#endif
uint16_t ADCee::usedpins = 0;
uint8_t ADCee::highestPin = 0;
int * ADCee::analogvals = NULL;
byte *ADCee::idarr = NULL;
static bool ADCusesHighPort = false;
/*
@@ -139,28 +142,17 @@ static bool ADCusesHighPort = false;
*/
int ADCee::init(uint8_t pin) {
uint8_t id = pin - A0;
byte n;
if (id >= NUM_ADC_INPUTS)
return -1023;
if (id > 7)
ADCusesHighPort = true;
pinMode(pin, INPUT);
int value = analogRead(pin);
if (analogvals == NULL) {
if (analogvals == NULL)
analogvals = (int *)calloc(NUM_ADC_INPUTS, sizeof(int));
for (n=0 ; n < NUM_ADC_INPUTS; n++) // set unreasonable value at startup as marker
analogvals[n] = -32768; // 16 bit int min value
idarr = (byte *)calloc(NUM_ADC_INPUTS+1, sizeof(byte)); // +1 for terminator value
for (n=0 ; n <= NUM_ADC_INPUTS; n++)
idarr[n] = 255; // set 255 as end of array marker
}
analogvals[id] = value; // store before enable by idarr[n]
for (n=0 ; n <= NUM_ADC_INPUTS; n++) {
if (idarr[n] == 255) {
idarr[n] = id;
break;
}
}
analogvals[id] = value;
usedpins |= (1<<id);
if (id > highestPin) highestPin = id;
return value;
}
int16_t ADCee::ADCmax() {
@@ -170,14 +162,14 @@ int16_t ADCee::ADCmax() {
* Read function ADCee::read(pin) to get value instead of analogRead(pin)
*/
int ADCee::read(uint8_t pin, bool fromISR) {
(void)fromISR; // AVR does ignore this arg
uint8_t id = pin - A0;
int a;
if ((usedpins & (1<<id) ) == 0)
return -1023;
// we do not need to check (analogvals == NULL)
// because usedpins would still be 0 in that case
noInterrupts();
a = analogvals[id];
interrupts();
if (!fromISR) noInterrupts();
int a = analogvals[id];
if (!fromISR) interrupts();
return a;
}
/*
@@ -186,7 +178,8 @@ int ADCee::read(uint8_t pin, bool fromISR) {
#pragma GCC push_options
#pragma GCC optimize ("-O3")
void ADCee::scan() {
static byte num = 0; // index into id array
static byte id = 0; // id and mask are the same thing but it is faster to
static uint16_t mask = 1; // increment and shift instead to calculate mask from id
static bool waiting = false;
if (waiting) {
@@ -198,26 +191,49 @@ void ADCee::scan() {
low = ADCL; //must read low before high
high = ADCH;
bitSet(ADCSRA, ADIF);
analogvals[idarr[num]] = (high << 8) | low;
analogvals[id] = (high << 8) | low;
// advance at least one track
#ifdef DEBUG_ADC
if (id == 1) TrackManager::track[1]->setBrake(0);
#endif
waiting = false;
id++;
mask = mask << 1;
if (id > highestPin) {
id = 0;
mask = 1;
}
}
if (!waiting) {
// cycle around in-use analogue pins
num++;
if (idarr[num] == 255)
num = 0;
// start new ADC aquire on id
if (usedpins == 0) // otherwise we would loop forever
return;
// look for a valid track to sample or until we are around
while (true) {
if (mask & usedpins) {
// start new ADC aquire on id
#if defined(ADCSRB) && defined(MUX5)
if (ADCusesHighPort) { // if we ever have started to use high pins)
if (idarr[num] > 7) // if we use a high ADC pin
bitSet(ADCSRB, MUX5); // set MUX5 bit
else
bitClear(ADCSRB, MUX5);
}
if (ADCusesHighPort) { // if we ever have started to use high pins)
if (id > 7) // if we use a high ADC pin
bitSet(ADCSRB, MUX5); // set MUX5 bit
else
bitClear(ADCSRB, MUX5);
}
#endif
ADMUX = (1 << REFS0) | (idarr[num] & 0x07); // select AVCC as reference and set MUX
bitSet(ADCSRA, ADSC); // start conversion
waiting = true;
ADMUX=(1<<REFS0)|(id & 0x07); //select AVCC as reference and set MUX
bitSet(ADCSRA,ADSC); // start conversion
#ifdef DEBUG_ADC
if (id == 1) TrackManager::track[1]->setBrake(1);
#endif
waiting = true;
return;
}
id++;
mask = mask << 1;
if (id > highestPin) {
id = 0;
mask = 1;
}
}
}
}
#pragma GCC pop_options
@@ -231,4 +247,4 @@ void ADCee::begin() {
//bitSet(ADCSRA, ADSC); //do not start the ADC yet. Done when we have set the MUX
interrupts();
}
#endif
#endif

View File

@@ -36,23 +36,25 @@
#include "DIAG.h"
#if defined(ARDUINO_NUCLEO_F411RE)
// Nucleo-64 boards don't have Serial1 defined by default
// Nucleo-64 boards don't have additional serial ports defined by default
HardwareSerial Serial1(PB7, PA15); // Rx=PB7, Tx=PA15 -- CN7 pins 17 and 21 - F411RE
// Serial2 is defined to use USART2 by default, but is in fact used as the diag console
// via the debugger on the Nucleo-64. It is therefore unavailable for other DCC-EX uses like WiFi, DFPlayer, etc.
// Let's define Serial6 as an additional serial port (the only other option for the Nucleo-64s)
HardwareSerial Serial3(PA12, PA11); // Rx=PA12, Tx=PA11 -- CN10 pins 12 and 14 - F411RE
HardwareSerial Serial6(PA12, PA11); // Rx=PA12, Tx=PA11 -- CN10 pins 12 and 14 - F411RE
#elif defined(ARDUINO_NUCLEO_F446RE)
// Nucleo-64 boards don't have Serial1 defined by default
// Nucleo-64 boards don't have additional serial ports defined by default
// On the F446RE, Serial1 isn't really useable as it's Rx/Tx pair sit on already used D2/D10 pins
// HardwareSerial Serial1(PA10, PB6); // Rx=PA10 (D2), Tx=PB6 (D10) -- CN10 pins 17 and 9 - F446RE
// Serial2 is defined to use USART2 by default, but is in fact used as the diag console
// via the debugger on the Nucleo-64. It is therefore unavailable for other DCC-EX uses like WiFi, DFPlayer, etc.
HardwareSerial Serial1(PC11, PC10); // Rx=PC11, Tx=PC10 -- USART3 - F446RE
HardwareSerial Serial3(PD2, PC12); // Rx=PC7, Tx=PC6 -- UART5 - F446RE
// NB: USART3 and USART6 are available but as yet undefined
// On the F446RE, Serial3 and Serial5 are easy to use:
HardwareSerial Serial3(PC11, PC10); // Rx=PC11, Tx=PC10 -- USART3 - F446RE
HardwareSerial Serial5(PD2, PC12); // Rx=PC7, Tx=PC6 -- UART5 - F446RE
// On the F446RE, Serial4 and Serial6 also use pins we can't readily map while using the Arduino pins
#elif defined(ARDUINO_NUCLEO_F412ZG) || defined(ARDUINO_NUCLEO_F429ZI) || defined(ARDUINO_NUCLEO_F446ZE)
// Nucleo-144 boards don't have Serial1 defined by default
HardwareSerial Serial1(PG9, PG14); // Rx=PG9, Tx=PG14 -- USART6
HardwareSerial Serial6(PG9, PG14); // Rx=PG9, Tx=PG14 -- USART6
// Serial3 is defined to use USART3 by default, but is in fact used as the diag console
// via the debugger on the Nucleo-144. It is therefore unavailable for other DCC-EX uses like WiFi, DFPlayer, etc.
#else
@@ -233,13 +235,16 @@ void DCCTimer::reset() {
while(true) {};
}
#define NUM_ADC_INPUTS NUM_ANALOG_INPUTS
// TODO: may need to use uint32_t on STMF4xx variants with > 16 analog inputs!
#if defined(ARDUINO_NUCLEO_F446RE) || defined(ARDUINO_NUCLEO_F429ZI) || defined(ARDUINO_NUCLEO_F446ZE)
#warning STM32 board selected not fully supported - only use ADC1 inputs 0-15 for current sensing!
#endif
// For now, define the max of 16 ports - some variants have more, but this not **yet** supported
#define NUM_ADC_INPUTS 16
// #define NUM_ADC_INPUTS NUM_ANALOG_INPUTS
uint16_t ADCee::usedpins = 0;
uint8_t ADCee::highestPin = 0;
int * ADCee::analogvals = NULL;
uint32_t * analogchans = NULL;
bool adc1configured = false;
@@ -310,6 +315,7 @@ int ADCee::init(uint8_t pin) {
analogvals[id] = value; // Store sampled value
analogchans[id] = adcchan; // Keep track of which ADC channel is used for reading this pin
usedpins |= (1 << id); // This pin is now ready
if (id > highestPin) highestPin = id; // Store our highest pin in use
DIAG(F("ADCee::init(): value=%d, channel=%d, id=%d"), value, adcchan, id);
@@ -352,7 +358,7 @@ void ADCee::scan() {
waiting = false;
id++;
mask = mask << 1;
if (mask == 0) { // the 1 has been shifted out
if (id > highestPin) { // the 1 has been shifted out
id = 0;
mask = 1;
}
@@ -374,9 +380,9 @@ void ADCee::scan() {
}
id++;
mask = mask << 1;
if (mask == 0) { // the 1 has been shifted out
id = 0;
mask = 1;
if (id > highestPin) {
id = 0;
mask = 1;
}
}
}

View File

@@ -1 +1 @@
#define GITHUB_SHA "devel-202306190642Z"
#define GITHUB_SHA "devel-202306182208Z"

View File

@@ -159,7 +159,11 @@ MotorDriver::MotorDriver(int16_t power_pin, byte signal_pin, byte signal_pin2, i
// senseFactorInternal, raw2mA(1000),mA2raw(1000));
}
// prepare values for current detection
sampleDelay = 0;
lastSampleTaken = millis();
progTripValue = mA2raw(TRIP_CURRENT_PROG);
}
bool MotorDriver::isPWMCapable() {
@@ -168,7 +172,6 @@ bool MotorDriver::isPWMCapable() {
void MotorDriver::setPower(POWERMODE mode) {
if (powerMode == mode) return;
bool on=mode==POWERMODE::ON;
if (on) {
// when switching a track On, we need to check the crrentOffset with the pin OFF
@@ -369,123 +372,63 @@ void MotorDriver::getFastPin(const FSH* type,int pin, bool input, FASTPIN & res
}
void MotorDriver::checkPowerOverload(bool useProgLimit, byte trackno) {
if (millis() - lastSampleTaken < sampleDelay) return;
lastSampleTaken = millis();
int tripValue= useProgLimit?progTripValue:getRawCurrentTripValue();
// Trackname for diag messages later
switch (powerMode) {
case POWERMODE::OFF:
if (overloadNow) {
// reset overload condition as we have just turned off power
// DIAG(F("OVERLOAD POFF OFF"));
overloadNow=false;
lastPowerChange = micros();
}
if (microsSinceLastPowerChange() > POWER_SAMPLE_ALL_GOOD) {
power_sample_overload_wait = POWER_SAMPLE_OVERLOAD_WAIT;
}
sampleDelay = POWER_SAMPLE_OFF_WAIT;
break;
case POWERMODE::ON:
// Check current
lastCurrent=getCurrentRaw();
if (lastCurrent < 0) {
// We have a fault pin condition to take care of
if (!overloadNow) {
// turn on overload condition as fault pin has gone active
// DIAG(F("OVERLOAD FPIN ON"));
overloadNow=true;
lastPowerChange = micros();
}
lastCurrent = -lastCurrent;
if (commonFaultPin) {
if (lastCurrent < tripValue) {
// probably other track, do a fast toggle.
setPower(POWERMODE::OVERLOAD); // Turn off, decide later how fast to turn on again
setPower(POWERMODE::ON); // maybe other track
// Write this after the fact as we want to turn on as fast as possible
// because we don't know which output actually triggered the fault pin
DIAG(F("COMMON FAULT PIN ACTIVE: POWERTOGGLE TRACK %c"), trackno + 'A');
}
} else {
if (lastCurrent < tripValue) {
if (power_sample_overload_wait <= (POWER_SAMPLE_OVERLOAD_WAIT * 10) && // almost virgin
microsSinceLastPowerChange() < POWER_SAMPLE_IGNORE_FAULT_LOW) {
// Ignore 50ms fault pin if no current
DIAG(F("TRACK %c FAULT PIN 50ms ignore"), trackno + 'A');
break;
}
lastCurrent = tripValue; // exaggerate so condition below (*) is true
// We have a fault pin condition to take care of
lastCurrent = -lastCurrent;
setPower(POWERMODE::OVERLOAD); // Turn off, decide later how fast to turn on again
if (commonFaultPin) {
if (lastCurrent < tripValue) {
setPower(POWERMODE::ON); // maybe other track
}
// Write this after the fact as we want to turn on as fast as possible
// because we don't know which output actually triggered the fault pin
DIAG(F("COMMON FAULT PIN ACTIVE: POWERTOGGLE TRACK %c"), trackno + 'A');
} else {
if (power_sample_overload_wait <= POWER_SAMPLE_OVERLOAD_WAIT && // virgin
microsSinceLastPowerChange() < POWER_SAMPLE_IGNORE_FAULT_HIGH) {
// Ignore 5ms fault pin if we see current
DIAG(F("TRACK %c FAULT PIN 5ms ignore"), trackno + 'A');
break;
}
DIAG(F("TRACK %c FAULT PIN ACTIVE - OVERLOAD"), trackno + 'A');
if (lastCurrent < tripValue) {
lastCurrent = tripValue; // exaggerate
}
}
DIAG(F("TRACK %c FAULT PIN ACTIVE"), trackno + 'A');
}
}
// // //
// above we looked at fault pin, below we look at current
// // //
if (lastCurrent < tripValue) { // see above (*)
if (overloadNow) {
// current is below trip value, turn off overload condition
// DIAG(F("OVERLOAD PON OFF"));
overloadNow=false;
lastPowerChange = micros();
}
if (microsSinceLastPowerChange() > POWER_SAMPLE_ALL_GOOD) {
power_sample_overload_wait = POWER_SAMPLE_OVERLOAD_WAIT;
}
if (lastCurrent < tripValue) {
sampleDelay = POWER_SAMPLE_ON_WAIT;
if(power_good_counter<100)
power_good_counter++;
else
if (power_sample_overload_wait>POWER_SAMPLE_OVERLOAD_WAIT) power_sample_overload_wait=POWER_SAMPLE_OVERLOAD_WAIT;
} else {
// too much current
if (!overloadNow) {
// current is over trip value, turn on overload condition
// DIAG(F("OVERLOAD PON ON"));
overloadNow=true;
lastPowerChange = micros();
}
unsigned long uSecs = microsSinceLastPowerChange();
if (power_sample_overload_wait > POWER_SAMPLE_OVERLOAD_WAIT || // not virgin
uSecs > POWER_SAMPLE_OFF_DELAY) {
// Overload has existed longer than delay (typ. 10ms)
setPower(POWERMODE::OVERLOAD);
if (overloadNow) {
// the setPower just turned off, so overload is now gone
// DIAG(F("OVERLOAD PON OFF"));
overloadNow=false;
lastPowerChange = micros();
}
unsigned int mA=raw2mA(lastCurrent);
unsigned int maxmA=raw2mA(tripValue);
DIAG(F("TRACK %c POWER OVERLOAD %dmA (limit %dmA) shutdown after %lus for %lus"),
trackno + 'A', mA, maxmA, uSecs, power_sample_overload_wait);
}
setPower(POWERMODE::OVERLOAD);
unsigned int mA=raw2mA(lastCurrent);
unsigned int maxmA=raw2mA(tripValue);
power_good_counter=0;
sampleDelay = power_sample_overload_wait;
DIAG(F("TRACK %c POWER OVERLOAD %dmA (limit %dmA) shutdown for %dms"), trackno + 'A', mA, maxmA, sampleDelay);
if (power_sample_overload_wait >= 10000)
power_sample_overload_wait = 10000;
else
power_sample_overload_wait *= 2;
}
break;
case POWERMODE::OVERLOAD:
if (overloadNow) {
// state overload mode means power is off, turn off overload condition flag as well
// DIAG(F("OVERLOAD POVER OFF"));
overloadNow=false;
lastPowerChange = micros();
}
// Try setting it back on after the OVERLOAD_WAIT
if (microsSinceLastPowerChange() > power_sample_overload_wait) {
// adjust next wait time
power_sample_overload_wait *= 2;
if (power_sample_overload_wait > POWER_SAMPLE_RETRY_MAX)
power_sample_overload_wait = POWER_SAMPLE_RETRY_MAX;
// power on test
case POWERMODE::OVERLOAD:
// Try setting it back on after the OVERLOAD_WAIT
setPower(POWERMODE::ON);
// here we change power but not the overloadNow as that was
// already changed to false when we entered POWERMODE::OVERLOAD
// so we need to set the lastPowerChange anyway.
lastPowerChange = micros();
DIAG(F("TRACK %c POWER RESTORE (was off %lus)"), trackno + 'A', power_sample_overload_wait);
}
break;
default:
break;
sampleDelay = POWER_SAMPLE_ON_WAIT;
// Debug code....
DIAG(F("TRACK %c POWER RESTORE (check %dms)"), trackno + 'A', sampleDelay);
break;
default:
sampleDelay = 999; // cant get here..meaningless statement to avoid compiler warning.
}
}

View File

@@ -186,16 +186,6 @@ class MotorDriver {
inline void setTrackLetter(char c) {
trackLetter = c;
};
// this returns how much time has passed since the last power change. If it
// was really long ago (approx > 52min) advance counter approx 35 min so that
// we are at 18 minutes again. Times for 32 bit unsigned long.
inline unsigned long microsSinceLastPowerChange() {
unsigned long now = micros();
unsigned long diff = now - lastPowerChange;
if (diff > (1UL << (7 *sizeof(unsigned long)))) // 2^(4*7)us = 268.4 seconds
lastPowerChange = now - 30000000UL; // 30 seconds ago
return diff;
};
#ifdef ANALOG_READ_INTERRUPT
bool sampleCurrentFromHW();
void startCurrentFromHW();
@@ -227,8 +217,8 @@ class MotorDriver {
int rawCurrentTripValue;
// current sampling
POWERMODE powerMode;
bool overloadNow = false;
unsigned long lastPowerChange; // timestamp in microseconds
unsigned long lastSampleTaken;
unsigned int sampleDelay;
int progTripValue;
int lastCurrent;
#ifdef ANALOG_READ_INTERRUPT
@@ -238,19 +228,10 @@ class MotorDriver {
int maxmA;
int tripmA;
// Times for overload management. Unit: microseconds.
// Base for wait time until power is turned on again
static const unsigned long POWER_SAMPLE_OVERLOAD_WAIT = 100UL;
// Time after we consider all faults old and forgotten
static const unsigned long POWER_SAMPLE_ALL_GOOD = 5000000UL;
// How long to ignore fault pin if current is under limit
static const unsigned long POWER_SAMPLE_IGNORE_FAULT_LOW = 50000UL;
// How long to ignore fault pin if current is higher than limit
static const unsigned long POWER_SAMPLE_IGNORE_FAULT_HIGH = 5000UL;
// How long to wait between overcurrent and turning off
static const unsigned long POWER_SAMPLE_OFF_DELAY = 10000UL;
// Upper limit for retry period
static const unsigned long POWER_SAMPLE_RETRY_MAX = 10000000UL;
// Wait times for power management. Unit: milliseconds
static const int POWER_SAMPLE_ON_WAIT = 100;
static const int POWER_SAMPLE_OFF_WAIT = 1000;
static const int POWER_SAMPLE_OVERLOAD_WAIT = 20;
// Trip current for programming track, 250mA. Change only if you really
// need to be non-NMRA-compliant because of decoders that are not either.

View File

@@ -52,20 +52,32 @@ Stream * WifiInterface::wifiStream;
#if (defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560))
#define NUM_SERIAL 3
#define SERIAL1 Serial1
#define SERIAL3 Serial3
#endif
#if defined(ARDUINO_ARCH_STM32)
// Handle serial ports availability on STM32 for variants!
// #undef NUM_SERIAL
#if defined(ARDUINO_NUCLEO_F411RE)
#define NUM_SERIAL 3
#define SERIAL1 Serial1
#define SERIAL3 Serial6
#elif defined(ARDUINO_NUCLEO_F446RE)
#define NUM_SERIAL 3
#define SERIAL1 Serial3
#define SERIAL3 Serial5
#elif defined(ARDUINO_NUCLEO_F412ZG) || defined(ARDUINO_NUCLEO_F429ZI) || defined(ARDUINO_NUCLEO_F446ZE)
#define NUM_SERIAL 2
#define SERIAL1 Serial6
#endif
#endif
#ifndef NUM_SERIAL
#define NUM_SERIAL 1
#define SERIAL1 Serial1
#endif
// For STM32 we need to define Serial3 in the platform specific
// DCCTimerSTM32.cpp file, we here make the assumption that it
// exists to link against.
#ifdef ARDUINO_ARCH_STM32
#if NUM_SERIAL > 2
extern HardwareSerial Serial3;
#endif
#endif
bool WifiInterface::setup(long serial_link_speed,
const FSH *wifiESSID,
const FSH *wifiPassword,
@@ -84,14 +96,15 @@ bool WifiInterface::setup(long serial_link_speed,
(void) port;
(void) channel;
#endif
// See if the WiFi is attached to the first serial port
#if NUM_SERIAL > 0 && !defined(SERIAL1_COMMANDS)
Serial1.begin(serial_link_speed);
wifiUp = setup(Serial1, wifiESSID, wifiPassword, hostname, port, channel);
SERIAL1.begin(serial_link_speed);
wifiUp = setup(SERIAL1, wifiESSID, wifiPassword, hostname, port, channel);
#endif
// Other serials are tried, depending on hardware.
// Currently only the Arduino Mega 2560 has usable Serial2
// Currently only the Arduino Mega 2560 has usable Serial2 (Nucleo-64 boards use Serial 2 for console!)
#if defined(ARDUINO_AVR_MEGA2560)
#if NUM_SERIAL > 1 && !defined(SERIAL2_COMMANDS)
if (wifiUp == WIFI_NOAT)
@@ -107,8 +120,8 @@ bool WifiInterface::setup(long serial_link_speed,
#if NUM_SERIAL > 2 && !defined(SERIAL3_COMMANDS)
if (wifiUp == WIFI_NOAT)
{
Serial3.begin(serial_link_speed);
wifiUp = setup(Serial3, wifiESSID, wifiPassword, hostname, port, channel);
SERIAL3.begin(serial_link_speed);
wifiUp = setup(SERIAL3, wifiESSID, wifiPassword, hostname, port, channel);
}
#endif

View File

@@ -147,8 +147,6 @@
#ifndef I2C_USE_WIRE
#define I2C_USE_WIRE
#endif
#undef NUM_SERIAL
#define NUM_SERIAL 3
/* TODO when ready
#elif defined(ARDUINO_ARCH_RP2040)

View File

@@ -188,7 +188,7 @@ platform = ststm32
board = nucleo_f446re
framework = arduino
lib_deps = ${env.lib_deps}
build_flags = -std=c++17 -Os -g2 -Wunused-variable -DDIAG_LOOPTIMES ; -DDIAG_IO
build_flags = -std=c++17 -Os -g2 -Wunused-variable ; -DDIAG_LOOPTIMES ; -DDIAG_IO
monitor_speed = 115200
monitor_echo = yes

View File

@@ -4,7 +4,8 @@
#include "StringFormatter.h"
#define VERSION "4.2.54"
#define VERSION "4.2.55"
// 4.2.55 - Optimize analog read for AVR
// 4.2.54 - EX8874 shield in config.example.h
// - Fix: Better warnings for pin number errors
// - Fix: Default roster list possible in Withrottle and <jR>