mirror of
https://github.com/DCC-EX/CommandStation-EX.git
synced 2024-12-24 05:11:24 +01:00
commit
8cff51b913
@ -67,6 +67,7 @@ const int16_t HASH_KEYWORD_RETRY = 25704;
|
|||||||
const int16_t HASH_KEYWORD_SPEED28 = -17064;
|
const int16_t HASH_KEYWORD_SPEED28 = -17064;
|
||||||
const int16_t HASH_KEYWORD_SPEED128 = 25816;
|
const int16_t HASH_KEYWORD_SPEED128 = 25816;
|
||||||
const int16_t HASH_KEYWORD_SERVO=27709;
|
const int16_t HASH_KEYWORD_SERVO=27709;
|
||||||
|
const int16_t HASH_KEYWORD_TT=2688;
|
||||||
const int16_t HASH_KEYWORD_VPIN=-415;
|
const int16_t HASH_KEYWORD_VPIN=-415;
|
||||||
const int16_t HASH_KEYWORD_A='A';
|
const int16_t HASH_KEYWORD_A='A';
|
||||||
const int16_t HASH_KEYWORD_C='C';
|
const int16_t HASH_KEYWORD_C='C';
|
||||||
@ -938,6 +939,10 @@ bool DCCEXParser::parseD(Print *stream, int16_t params, int16_t p[])
|
|||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
case HASH_KEYWORD_TT: // <D TT vpin steps activity>
|
||||||
|
IODevice::writeAnalogue(p[1], p[2], params>3 ? p[3] : 0);
|
||||||
|
break;
|
||||||
|
|
||||||
default: // invalid/unknown
|
default: // invalid/unknown
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -78,6 +78,7 @@
|
|||||||
#undef LATCH
|
#undef LATCH
|
||||||
#undef LCD
|
#undef LCD
|
||||||
#undef LCN
|
#undef LCN
|
||||||
|
#undef MOVETT
|
||||||
#undef ONACTIVATE
|
#undef ONACTIVATE
|
||||||
#undef ONACTIVATEL
|
#undef ONACTIVATEL
|
||||||
#undef ONAMBER
|
#undef ONAMBER
|
||||||
@ -187,6 +188,7 @@
|
|||||||
#define LATCH(sensor_id)
|
#define LATCH(sensor_id)
|
||||||
#define LCD(row,msg)
|
#define LCD(row,msg)
|
||||||
#define LCN(msg)
|
#define LCN(msg)
|
||||||
|
#define MOVETT(id,steps,activity)
|
||||||
#define ONACTIVATE(addr,subaddr)
|
#define ONACTIVATE(addr,subaddr)
|
||||||
#define ONACTIVATEL(linear)
|
#define ONACTIVATEL(linear)
|
||||||
#define ONAMBER(signal_id)
|
#define ONAMBER(signal_id)
|
||||||
|
@ -267,6 +267,7 @@ const FLASH int16_t RMFT2::SignalDefinitions[] = {
|
|||||||
#define LATCH(sensor_id) OPCODE_LATCH,V(sensor_id),
|
#define LATCH(sensor_id) OPCODE_LATCH,V(sensor_id),
|
||||||
#define LCD(id,msg) PRINT(msg)
|
#define LCD(id,msg) PRINT(msg)
|
||||||
#define LCN(msg) PRINT(msg)
|
#define LCN(msg) PRINT(msg)
|
||||||
|
#define MOVETT(id,steps,activity) OPCODE_SERVO,V(id),OPCODE_PAD,V(steps),OPCODE_PAD,V(EXTurntable::activity),OPCODE_PAD,V(0),
|
||||||
#define ONACTIVATE(addr,subaddr) OPCODE_ONACTIVATE,V(addr<<2|subaddr),
|
#define ONACTIVATE(addr,subaddr) OPCODE_ONACTIVATE,V(addr<<2|subaddr),
|
||||||
#define ONACTIVATEL(linear) OPCODE_ONACTIVATE,V(linear+3),
|
#define ONACTIVATEL(linear) OPCODE_ONACTIVATE,V(linear+3),
|
||||||
#define ONAMBER(signal_id) OPCODE_ONAMBER,V(signal_id),
|
#define ONAMBER(signal_id) OPCODE_ONAMBER,V(signal_id),
|
||||||
|
33
IODevice.h
33
IODevice.h
@ -364,6 +364,39 @@ private:
|
|||||||
uint8_t *_pinInUse;
|
uint8_t *_pinInUse;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/*
|
||||||
|
* IODevice subclass for EX-Turntable.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class EXTurntable : public IODevice {
|
||||||
|
public:
|
||||||
|
static void create(VPIN firstVpin, int nPins, uint8_t I2CAddress);
|
||||||
|
// Constructor
|
||||||
|
EXTurntable(VPIN firstVpin, int nPins, uint8_t I2CAddress);
|
||||||
|
enum ActivityNumber : uint8_t {
|
||||||
|
Turn = 0, // Rotate turntable, maintain phase
|
||||||
|
Turn_PInvert = 1, // Rotate turntable, invert phase
|
||||||
|
Home = 2, // Initiate homing
|
||||||
|
Calibrate = 3, // Initiate calibration sequence
|
||||||
|
LED_On = 4, // Turn LED on
|
||||||
|
LED_Slow = 5, // Set LED to a slow blink
|
||||||
|
LED_Fast = 6, // Set LED to a fast blink
|
||||||
|
LED_Off = 7, // Turn LED off
|
||||||
|
Acc_On = 8, // Turn accessory pin on
|
||||||
|
Acc_Off = 9, // Turn accessory pin off
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Device-specific write function.
|
||||||
|
void _begin() override;
|
||||||
|
void _loop(unsigned long currentMicros) override;
|
||||||
|
int _read(VPIN vpin) override;
|
||||||
|
void _writeAnalogue(VPIN vpin, int value, uint8_t activity, uint16_t duration) override;
|
||||||
|
void _display() override;
|
||||||
|
uint8_t _stepperStatus;
|
||||||
|
};
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#include "IO_MCP23008.h"
|
#include "IO_MCP23008.h"
|
||||||
|
121
IO_EXTurntable.h
Normal file
121
IO_EXTurntable.h
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
/*
|
||||||
|
* © 2021, Peter Cole. All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is part of CommandStation-EX
|
||||||
|
*
|
||||||
|
* This 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, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* It 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 CommandStation. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The IO_EXTurntable device driver is used to control a turntable via an Arduino with a stepper motor over I2C.
|
||||||
|
*
|
||||||
|
* The EX-Turntable code lives in a separate repo (https://github.com/DCC-EX/Turntable-EX) and contains the stepper motor logic.
|
||||||
|
*
|
||||||
|
* This device driver sends a step position to Turntable-EX to indicate the step position to move to using either of these commands:
|
||||||
|
* <D TT vpin steps activity> in the serial console
|
||||||
|
* MOVETT(vpin, steps, activity) in EX-RAIL
|
||||||
|
* Refer to the documentation for further information including the valid activities.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef IO_EXTurntable_h
|
||||||
|
#define IO_EXTurntable_h
|
||||||
|
|
||||||
|
#include "IODevice.h"
|
||||||
|
#include "I2CManager.h"
|
||||||
|
#include "DIAG.h"
|
||||||
|
|
||||||
|
void EXTurntable::create(VPIN firstVpin, int nPins, uint8_t I2CAddress) {
|
||||||
|
new EXTurntable(firstVpin, nPins, I2CAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
EXTurntable::EXTurntable(VPIN firstVpin, int nPins, uint8_t I2CAddress) {
|
||||||
|
_firstVpin = firstVpin;
|
||||||
|
_nPins = nPins;
|
||||||
|
_I2CAddress = I2CAddress;
|
||||||
|
addDevice(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialisation of TurntableEX
|
||||||
|
void EXTurntable::_begin() {
|
||||||
|
I2CManager.begin();
|
||||||
|
I2CManager.setClock(1000000);
|
||||||
|
if (I2CManager.exists(_I2CAddress)) {
|
||||||
|
#ifdef DIAG_IO
|
||||||
|
_display();
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
_deviceState = DEVSTATE_FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Processing loop to obtain status of stepper
|
||||||
|
// 0 = finished moving and in correct position
|
||||||
|
// 1 = still moving
|
||||||
|
void EXTurntable::_loop(unsigned long currentMicros) {
|
||||||
|
uint8_t readBuffer[1];
|
||||||
|
I2CManager.read(_I2CAddress, readBuffer, 1);
|
||||||
|
_stepperStatus = readBuffer[0];
|
||||||
|
// DIAG(F("Turntable-EX returned status: %d"), _stepperStatus);
|
||||||
|
delayUntil(currentMicros + 500000); // Wait 500ms before checking again, turntables turn slowly
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read returns status as obtained in our loop.
|
||||||
|
// Return false if our status value is invalid.
|
||||||
|
int EXTurntable::_read(VPIN vpin) {
|
||||||
|
if (_deviceState == DEVSTATE_FAILED) return 0;
|
||||||
|
// DIAG(F("_read status: %d"), _stepperStatus);
|
||||||
|
if (_stepperStatus > 1) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return _stepperStatus;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// writeAnalogue to send the steps and activity to Turntable-EX.
|
||||||
|
// Sends 3 bytes containing the MSB and LSB of the step count, and activity.
|
||||||
|
// value contains the steps, bit shifted to MSB + LSB.
|
||||||
|
// activity contains the activity flag as per this list:
|
||||||
|
//
|
||||||
|
// Turn = 0, // Rotate turntable, maintain phase
|
||||||
|
// Turn_PInvert = 1, // Rotate turntable, invert phase
|
||||||
|
// Home = 2, // Initiate homing
|
||||||
|
// Calibrate = 3, // Initiate calibration sequence
|
||||||
|
// LED_On = 4, // Turn LED on
|
||||||
|
// LED_Slow = 5, // Set LED to a slow blink
|
||||||
|
// LED_Fast = 6, // Set LED to a fast blink
|
||||||
|
// LED_Off = 7, // Turn LED off
|
||||||
|
// Acc_On = 8, // Turn accessory pin on
|
||||||
|
// Acc_Off = 9 // Turn accessory pin off
|
||||||
|
void EXTurntable::_writeAnalogue(VPIN vpin, int value, uint8_t activity, uint16_t duration) {
|
||||||
|
if (_deviceState == DEVSTATE_FAILED) return;
|
||||||
|
uint8_t stepsMSB = value >> 8;
|
||||||
|
uint8_t stepsLSB = value & 0xFF;
|
||||||
|
#ifdef DIAG_IO
|
||||||
|
DIAG(F("TurntableEX WriteAnalogue Vpin:%d Value:%d Activity:%d Duration:%d"),
|
||||||
|
vpin, value, activity, duration);
|
||||||
|
DIAG(F("I2CManager write I2C Address:%d stepsMSB:%d stepsLSB:%d activity:%d"),
|
||||||
|
_I2CAddress, stepsMSB, stepsLSB, activity);
|
||||||
|
#endif
|
||||||
|
_stepperStatus = 1; // Tell the device driver Turntable-EX is busy
|
||||||
|
I2CManager.write(_I2CAddress, 3, stepsMSB, stepsLSB, activity);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display Turnetable-EX device driver info.
|
||||||
|
void EXTurntable::_display() {
|
||||||
|
DIAG(F("TurntableEX I2C:x%x Configured on Vpins:%d-%d %S"), _I2CAddress, (int)_firstVpin,
|
||||||
|
(int)_firstVpin+_nPins-1, (_deviceState==DEVSTATE_FAILED) ? F("OFFLINE") : F(""));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
101
myEX-Turntable.example.h
Normal file
101
myEX-Turntable.example.h
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
/**************************************************************************************************
|
||||||
|
* This is an example automation file to control EX-Turntable using recommended techniques.
|
||||||
|
**************************************************************************************************
|
||||||
|
* INSTRUCTIONS
|
||||||
|
**************************************************************************************************
|
||||||
|
* To use this example file as the starting point for your layout, there are two options:
|
||||||
|
*
|
||||||
|
* 1. If you don't have an existing "myAutomation.h" file, simply rename "myEX-Turntable.example.h" to
|
||||||
|
* "myAutomation.h".
|
||||||
|
* 2. If you have an existing "myAutomation.h" file, rename "myEX-Turntable.example.h" to "myEX-Turntable.h",
|
||||||
|
* and then include it by adding the line below at the end of your existing "myAutomation.h", on a
|
||||||
|
* line of its own:
|
||||||
|
*
|
||||||
|
* #include "myEX-Turntable.h"
|
||||||
|
*
|
||||||
|
* Note that there are further instructions in the documentation at https://dcc-ex.com/.
|
||||||
|
*************************************************************************************************/
|
||||||
|
|
||||||
|
/**************************************************************************************************
|
||||||
|
* The MOVETT() command below will automatically move your turntable to the defined step position on
|
||||||
|
* start up.
|
||||||
|
*
|
||||||
|
* If you do not wish this to occur, simply comment the line out.
|
||||||
|
*
|
||||||
|
* NOTE: If you are including this file at the end of an existing "myAutomation.h" file, you will likely
|
||||||
|
* need to move this line to the beginning of your existing "myAutomation.h" file in order for it to
|
||||||
|
* be effective.
|
||||||
|
*************************************************************************************************/
|
||||||
|
MOVETT(600, 114, Turn)
|
||||||
|
DONE
|
||||||
|
|
||||||
|
// For Conductor level users who wish to just use EX-Turntable, you don't need to understand this
|
||||||
|
// and can move to defining the turntable positions below. You must, however, ensure this remains
|
||||||
|
// before any position definitions or you will get compile errors when uploading.
|
||||||
|
//
|
||||||
|
// Definition of the EX_TURNTABLE macro to correctly create the ROUTEs required for each position.
|
||||||
|
// This includes RESERVE()/FREE() to protect any automation activities.
|
||||||
|
//
|
||||||
|
#define EX_TURNTABLE(route_id, reserve_id, vpin, steps, activity, desc) \
|
||||||
|
ROUTE(route_id, desc) \
|
||||||
|
RESERVE(reserve_id) \
|
||||||
|
MOVETT(vpin, steps, activity) \
|
||||||
|
WAITFOR(vpin) \
|
||||||
|
FREE(reserve_id) \
|
||||||
|
DONE
|
||||||
|
|
||||||
|
/**************************************************************************************************
|
||||||
|
* TURNTABLE POSITION DEFINITIONS
|
||||||
|
*************************************************************************************************/
|
||||||
|
// EX_TURNTABLE(route_id, reserve_id, vpin, steps, activity, desc)
|
||||||
|
//
|
||||||
|
// route_id = A unique number for each defined route, the route is what appears in throttles
|
||||||
|
// reserve_id = A unique reservation number (0 - 255) to ensure nothing interferes with automation
|
||||||
|
// vpin = The Vpin defined for the Turntable-EX device driver, default is 600
|
||||||
|
// steps = The target step position
|
||||||
|
// activity = The activity performed for this ROUTE (Note do not enclose in quotes "")
|
||||||
|
// desc = Description that will appear in throttles (Must use quotes "")
|
||||||
|
//
|
||||||
|
EX_TURNTABLE(TTRoute1, Turntable, 600, 114, Turn, "Position 1")
|
||||||
|
EX_TURNTABLE(TTRoute2, Turntable, 600, 227, Turn, "Position 2")
|
||||||
|
EX_TURNTABLE(TTRoute3, Turntable, 600, 341, Turn, "Position 3")
|
||||||
|
EX_TURNTABLE(TTRoute4, Turntable, 600, 2159, Turn, "Position 4")
|
||||||
|
EX_TURNTABLE(TTRoute5, Turntable, 600, 2273, Turn, "Position 5")
|
||||||
|
EX_TURNTABLE(TTRoute6, Turntable, 600, 2386, Turn, "Position 6")
|
||||||
|
EX_TURNTABLE(TTRoute7, Turntable, 600, 0, Home, "Home turntable")
|
||||||
|
|
||||||
|
// Pre-defined aliases to ensure unique IDs are used.
|
||||||
|
// Turntable reserve ID, valid is 0 - 255
|
||||||
|
ALIAS(Turntable, 255)
|
||||||
|
|
||||||
|
// Turntable ROUTE ID reservations, using <? TTRouteX> for uniqueness:
|
||||||
|
ALIAS(TTRoute1)
|
||||||
|
ALIAS(TTRoute2)
|
||||||
|
ALIAS(TTRoute3)
|
||||||
|
ALIAS(TTRoute4)
|
||||||
|
ALIAS(TTRoute5)
|
||||||
|
ALIAS(TTRoute6)
|
||||||
|
ALIAS(TTRoute7)
|
||||||
|
ALIAS(TTRoute8)
|
||||||
|
ALIAS(TTRoute9)
|
||||||
|
ALIAS(TTRoute10)
|
||||||
|
ALIAS(TTRoute11)
|
||||||
|
ALIAS(TTRoute12)
|
||||||
|
ALIAS(TTRoute13)
|
||||||
|
ALIAS(TTRoute14)
|
||||||
|
ALIAS(TTRoute15)
|
||||||
|
ALIAS(TTRoute16)
|
||||||
|
ALIAS(TTRoute17)
|
||||||
|
ALIAS(TTRoute18)
|
||||||
|
ALIAS(TTRoute19)
|
||||||
|
ALIAS(TTRoute20)
|
||||||
|
ALIAS(TTRoute21)
|
||||||
|
ALIAS(TTRoute22)
|
||||||
|
ALIAS(TTRoute23)
|
||||||
|
ALIAS(TTRoute24)
|
||||||
|
ALIAS(TTRoute25)
|
||||||
|
ALIAS(TTRoute26)
|
||||||
|
ALIAS(TTRoute27)
|
||||||
|
ALIAS(TTRoute28)
|
||||||
|
ALIAS(TTRoute29)
|
||||||
|
ALIAS(TTRoute30)
|
Loading…
Reference in New Issue
Block a user