mirror of
https://github.com/DCC-EX/CommandStation-EX.git
synced 2024-11-30 03:26:13 +01:00
do analogRead without need for noInterrupt - first test
This commit is contained in:
parent
052f5807f0
commit
c47e9b79ca
|
@ -45,7 +45,14 @@ INTERRUPT_CALLBACK interruptHandler=0;
|
||||||
void DCCTimer::begin(INTERRUPT_CALLBACK callback) {
|
void DCCTimer::begin(INTERRUPT_CALLBACK callback) {
|
||||||
interruptHandler=callback;
|
interruptHandler=callback;
|
||||||
noInterrupts();
|
noInterrupts();
|
||||||
ADCSRA = (ADCSRA & 0b11111000) | 0b00000100; // speed up analogRead sample time
|
// ADCSRA = (ADCSRA & 0b11111000) | 0b00000100; // speed up analogRead sample time
|
||||||
|
// Set up ADC for free running mode
|
||||||
|
ADMUX=(1<<REFS0); //select AVCC as reference. We set MUX later
|
||||||
|
//ADCSRB = 0; //set free running mode
|
||||||
|
//ADCSRA = (1<<ADEN)|(1<< ADATE)|(1<<ADPS2)|(1<<ADPS0)|4;
|
||||||
|
ADCSRA = (1<<ADEN)|(1 << ADPS2);
|
||||||
|
//bitSet(ADCSRA, ADSC); //start the ADC
|
||||||
|
|
||||||
TCCR1A = 0;
|
TCCR1A = 0;
|
||||||
ICR1 = CLOCK_CYCLES;
|
ICR1 = CLOCK_CYCLES;
|
||||||
TCNT1 = 0;
|
TCNT1 = 0;
|
||||||
|
|
|
@ -85,7 +85,7 @@ void DCCWaveform::interruptHandler() {
|
||||||
mainTrack.state=stateTransform[mainTrack.state];
|
mainTrack.state=stateTransform[mainTrack.state];
|
||||||
progTrack.state=stateTransform[progTrack.state];
|
progTrack.state=stateTransform[progTrack.state];
|
||||||
|
|
||||||
|
TrackManager::sampleCurrent();
|
||||||
// WAVE_PENDING means we dont yet know what the next bit is
|
// WAVE_PENDING means we dont yet know what the next bit is
|
||||||
if (mainTrack.state==WAVE_PENDING) mainTrack.interrupt2();
|
if (mainTrack.state==WAVE_PENDING) mainTrack.interrupt2();
|
||||||
if (progTrack.state==WAVE_PENDING) progTrack.interrupt2();
|
if (progTrack.state==WAVE_PENDING) progTrack.interrupt2();
|
||||||
|
|
|
@ -223,9 +223,13 @@ int MotorDriver::getCurrentRaw() {
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
current = local_adc1_get_raw(pinToADC1Channel(currentPin))-senseOffset;
|
current = local_adc1_get_raw(pinToADC1Channel(currentPin))-senseOffset;
|
||||||
#else
|
#else
|
||||||
noInterrupts();
|
// noInterrupts();
|
||||||
current = analogRead(currentPin)-senseOffset;
|
//current = analogRead(currentPin)-senseOffset;
|
||||||
interrupts();
|
current = sampleCurrent-senseOffset;
|
||||||
|
DIAG(F("%d %d"), current, sampleCurrentTimestamp);
|
||||||
|
if ((millis() - sampleCurrentTimestamp) > 3)
|
||||||
|
DIAG(F("Current sample old %d"), millis() - sampleCurrentTimestamp);
|
||||||
|
//interrupts();
|
||||||
#endif
|
#endif
|
||||||
if (current<0) current=0-current;
|
if (current<0) current=0-current;
|
||||||
if ((faultPin != UNUSED_PIN) && isLOW(fastFaultPin) && powerMode==POWERMODE::ON)
|
if ((faultPin != UNUSED_PIN) && isLOW(fastFaultPin) && powerMode==POWERMODE::ON)
|
||||||
|
@ -233,6 +237,42 @@ int MotorDriver::getCurrentRaw() {
|
||||||
return current;
|
return current;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
* This should only be called in interrupt context
|
||||||
|
* Copies current value from HW to cached value in
|
||||||
|
* Motordriver.
|
||||||
|
*/
|
||||||
|
#pragma GCC push_options
|
||||||
|
#pragma GCC optimize ("-O3")
|
||||||
|
bool MotorDriver::sampleCurrentFromHW() {
|
||||||
|
#if defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560)
|
||||||
|
const byte mask = 7;
|
||||||
|
#else
|
||||||
|
const byte mask = 31;
|
||||||
|
#endif
|
||||||
|
byte low, high;
|
||||||
|
//if (!bit_is_set(ADCSRA, ADIF))
|
||||||
|
if (bit_is_set(ADCSRA, ADSC))
|
||||||
|
return false;
|
||||||
|
// if ((ADMUX & mask) != (currentPin - A0))
|
||||||
|
// return false;
|
||||||
|
low = ADCL; //must read low before high
|
||||||
|
high = ADCH;
|
||||||
|
bitSet(ADCSRA, ADIF);
|
||||||
|
sampleCurrent = (high << 8) | low;
|
||||||
|
sampleCurrentTimestamp = millis();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
void MotorDriver::startCurrentFromHW() {
|
||||||
|
#if defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560)
|
||||||
|
const byte mask = 7;
|
||||||
|
#else
|
||||||
|
const byte mask = 31;
|
||||||
|
#endif
|
||||||
|
ADMUX=(1<<REFS0)|((currentPin-A0) & mask); //select AVCC as reference and set MUX
|
||||||
|
bitSet(ADCSRA,ADSC); // start conversion
|
||||||
|
}
|
||||||
|
#pragma GCC pop_options
|
||||||
|
|
||||||
void MotorDriver::setDCSignal(byte speedcode) {
|
void MotorDriver::setDCSignal(byte speedcode) {
|
||||||
if (brakePin == UNUSED_PIN)
|
if (brakePin == UNUSED_PIN)
|
||||||
|
@ -296,7 +336,8 @@ int MotorDriver::getCurrentRawInInterrupt() {
|
||||||
#ifdef ARDUINO_ARCH_ESP32 //On ESP we do all in loop() instead of in interrupt
|
#ifdef ARDUINO_ARCH_ESP32 //On ESP we do all in loop() instead of in interrupt
|
||||||
return getCurrentRaw();
|
return getCurrentRaw();
|
||||||
#else
|
#else
|
||||||
return analogRead(currentPin)-senseOffset;
|
//return analogRead(currentPin)-senseOffset;
|
||||||
|
return getCurrentRaw();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -183,6 +183,8 @@ class MotorDriver {
|
||||||
isProgTrack = on;
|
isProgTrack = on;
|
||||||
}
|
}
|
||||||
void checkPowerOverload(bool useProgLimit, byte trackno);
|
void checkPowerOverload(bool useProgLimit, byte trackno);
|
||||||
|
bool sampleCurrentFromHW();
|
||||||
|
void startCurrentFromHW();
|
||||||
private:
|
private:
|
||||||
bool isProgTrack = false; // tells us if this is a prog track
|
bool isProgTrack = false; // tells us if this is a prog track
|
||||||
void getFastPin(const FSH* type,int pin, bool input, FASTPIN & result);
|
void getFastPin(const FSH* type,int pin, bool input, FASTPIN & result);
|
||||||
|
@ -212,6 +214,8 @@ class MotorDriver {
|
||||||
unsigned int sampleDelay;
|
unsigned int sampleDelay;
|
||||||
int progTripValue;
|
int progTripValue;
|
||||||
int lastCurrent;
|
int lastCurrent;
|
||||||
|
unsigned long sampleCurrentTimestamp;
|
||||||
|
uint16_t sampleCurrent;
|
||||||
int maxmA;
|
int maxmA;
|
||||||
int tripmA;
|
int tripmA;
|
||||||
|
|
||||||
|
|
|
@ -54,6 +54,40 @@ int16_t TrackManager::joinRelay=UNUSED_PIN;
|
||||||
byte TrackManager::tempProgTrack=MAX_TRACKS+1;
|
byte TrackManager::tempProgTrack=MAX_TRACKS+1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* sampleCurrent() runs from Interrupt
|
||||||
|
*/
|
||||||
|
void TrackManager::sampleCurrent() {
|
||||||
|
static byte tr = 0;
|
||||||
|
static bool waiting = false;
|
||||||
|
byte count = MAX_TRACKS-1;
|
||||||
|
|
||||||
|
if (waiting) {
|
||||||
|
if (! track[tr]->sampleCurrentFromHW()) {
|
||||||
|
return; // no result, continue to wait
|
||||||
|
}
|
||||||
|
// found value, advance at least one track
|
||||||
|
waiting = false;
|
||||||
|
tr++;
|
||||||
|
if (tr >= MAX_TRACKS) tr = 0;
|
||||||
|
}
|
||||||
|
if (!waiting) {
|
||||||
|
// look for a valid track to sample or until we are around
|
||||||
|
while (count) {
|
||||||
|
if (trackMode[tr] & ( TRACK_MODE_MAIN|TRACK_MODE_PROG|TRACK_MODE_DC|TRACK_MODE_DCX|TRACK_MODE_EXT )) {
|
||||||
|
track[tr]->startCurrentFromHW();
|
||||||
|
waiting = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tr++;
|
||||||
|
if (tr >= MAX_TRACKS) tr = 0;
|
||||||
|
count--;
|
||||||
|
}
|
||||||
|
if (count == 0) {
|
||||||
|
DIAG(F("WRONG"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// The setup call is done this way so that the tracks can be in a list
|
// The setup call is done this way so that the tracks can be in a list
|
||||||
// from the config... the tracks default to NULL in the declaration
|
// from the config... the tracks default to NULL in the declaration
|
||||||
|
|
|
@ -27,8 +27,9 @@
|
||||||
#include "MotorDriver.h"
|
#include "MotorDriver.h"
|
||||||
// Virtualised Motor shield multi-track hardware Interface
|
// Virtualised Motor shield multi-track hardware Interface
|
||||||
|
|
||||||
enum TRACK_MODE : byte {TRACK_MODE_OFF, TRACK_MODE_MAIN, TRACK_MODE_PROG,
|
// use powers of two so we can do logical and/or on the track modes in if clauses.
|
||||||
TRACK_MODE_DC, TRACK_MODE_DCX, TRACK_MODE_EXT};
|
enum TRACK_MODE : byte {TRACK_MODE_OFF = 1, TRACK_MODE_MAIN = 2, TRACK_MODE_PROG = 4,
|
||||||
|
TRACK_MODE_DC = 8, TRACK_MODE_DCX = 16, TRACK_MODE_EXT = 32};
|
||||||
|
|
||||||
// These constants help EXRAIL macros say SET_TRACK(2,mode) OR SET_TRACK(C,mode) etc.
|
// These constants help EXRAIL macros say SET_TRACK(2,mode) OR SET_TRACK(C,mode) etc.
|
||||||
const byte TRACK_NUMBER_0=0, TRACK_NUMBER_A=0;
|
const byte TRACK_NUMBER_0=0, TRACK_NUMBER_A=0;
|
||||||
|
@ -75,11 +76,11 @@ class TrackManager {
|
||||||
static void setJoin(bool join);
|
static void setJoin(bool join);
|
||||||
static bool isJoined() { return progTrackSyncMain;}
|
static bool isJoined() { return progTrackSyncMain;}
|
||||||
static void setJoinRelayPin(byte joinRelayPin);
|
static void setJoinRelayPin(byte joinRelayPin);
|
||||||
|
static void sampleCurrent();
|
||||||
static int16_t joinRelay;
|
static int16_t joinRelay;
|
||||||
static bool progTrackSyncMain; // true when prog track is a siding switched to main
|
static bool progTrackSyncMain; // true when prog track is a siding switched to main
|
||||||
static bool progTrackBoosted; // true when prog track is not current limited
|
static bool progTrackBoosted; // true when prog track is not current limited
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void addTrack(byte t, MotorDriver* driver);
|
static void addTrack(byte t, MotorDriver* driver);
|
||||||
static byte lastTrack;
|
static byte lastTrack;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user