1
0
mirror of https://github.com/DCC-EX/CommandStation-EX.git synced 2024-12-24 05:11:24 +01:00

Merge pull request #252 from DCC-EX/add-EX-Turntable

Add ex turntable
This commit is contained in:
habazut 2022-08-14 00:47:35 +02:00 committed by GitHub
commit 8cff51b913
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 263 additions and 0 deletions

View File

@ -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;
} }

View File

@ -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)

View File

@ -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),

View File

@ -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
View 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
View 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)