public override bool[] GET_MCU_Status(RadioTelescopeAxisEnum axis) //set { bool[] stuf = new bool[33]; for (int i = 0; i < 32; i++) { stuf[i] = true; } return(stuf); }
public override bool Start_jog(RadioTelescopeAxisEnum axis, int speed, bool clockwise) { ushort adress = MCUConstants.ACTUAL_MCU_WRITE_REGISTER_START_ADDRESS, dir; if (clockwise) { dir = 0x0080; } else { dir = 0x0100; } // reserved msb speed lsb speed acc dcc reserved ushort[] data = new ushort[] { dir, 0x0003, 0x0, 0x0, (ushort)(speed >> 16), (ushort)speed, 50, 25, 0x0, 0x0 };// this is a jog comand for a single axis RadioTelescopeAxisEnum jogging_axies = Is_jogging(); switch (axis) { case RadioTelescopeAxisEnum.AZIMUTH: { break; } case RadioTelescopeAxisEnum.ELEVATION: { adress = MCUConstants.ACTUAL_MCU_WRITE_REGISTER_START_ADDRESS + 10; break; } case RadioTelescopeAxisEnum.BOTH: { ushort[] data2 = new ushort[data.Length * 2]; data.CopyTo(data2, 0); data.CopyTo(data2, data.Length); data = data2; break; } default: { throw new ArgumentException("Invalid RadioTelescopeAxisEnum value can be AZIMUTH, ELEVATION or BOTH got: " + axis); } } MCUModbusMaster.WriteMultipleRegisters(adress, data); return(true); //throw new NotImplementedException(); }
/// <summary> /// get an array of boolens representiing the register described on pages 76 -79 of the mcu documentation /// does not suport RadioTelescopeAxisEnum.BOTH /// see <see cref="MCUConstants.MCUStatusBitsMSW"/> for description of each bit /// </summary> public override bool[] GET_MCU_Status(RadioTelescopeAxisEnum axis) { ushort start = 0; if (axis == RadioTelescopeAxisEnum.ELEVATION) { start = 10; } ushort[] data = MCU.ReadMCURegisters(start, 2); bool[] target = new bool[32]; for (int i = 0; i < 16; i++) { target[i] = ((data[0] >> i) & 1) == 1; target[i + 16] = ((data[1] >> i) & 1) == 1; } return(target); }
/// <summary> /// Gets the direction that the specfied axis is moving. /// </summary> /// <param name="axis">Azimuth or elevation.</param> /// <returns>The direction that the specfied axis is spinning.</returns> public override RadioTelescopeDirectionEnum GetRadioTelescopeDirectionEnum(RadioTelescopeAxisEnum axis) { ushort[] directionData; switch (axis) { //Axes must be checked independently because the MCU commands for motor moves have the same value for both Az and El case RadioTelescopeAxisEnum.AZIMUTH: directionData = MCU.ReadMCURegisters(0, 1); if ((directionData[(int)MCUConstants.MCUOutputRegs.AZ_Status_Bist_MSW] >> (int)MCUConstants.MCUStatusBitsMSW.CCW_Motion & 0b1) == 1) { return(RadioTelescopeDirectionEnum.CounterclockwiseOrPositive); } if ((directionData[(int)MCUConstants.MCUOutputRegs.AZ_Status_Bist_MSW] >> (int)MCUConstants.MCUStatusBitsMSW.CW_Motion & 0b1) == 1) { return(RadioTelescopeDirectionEnum.ClockwiseOrNegative); } break; case RadioTelescopeAxisEnum.ELEVATION: //in practice, only need to check the elevation directionData = MCU.ReadMCURegisters(10, 1); if (((directionData[(int)MCUConstants.MCUOutputRegs.EL_Status_Bist_MSW - 10] >> (int)MCUConstants.MCUStatusBitsMSW.CCW_Motion) & 0b1) == 1) { return(RadioTelescopeDirectionEnum.CounterclockwiseOrPositive); } if (((directionData[(int)MCUConstants.MCUOutputRegs.EL_Status_Bist_MSW - 10] >> (int)MCUConstants.MCUStatusBitsMSW.CW_Motion) & 0b1) == 1) { return(RadioTelescopeDirectionEnum.ClockwiseOrNegative); } break; default: //This function can only accept a single axis (either Az or El) //see comment at top of function throw new ArgumentException(); } return(RadioTelescopeDirectionEnum.None); }
/// <summary> /// Method used to request that all of the Radio Telescope's movement comes /// to an immediate stop. /// /// The implementation of this functionality is on a "per-RT" basis, as /// in this may or may not work, it depends on if the derived /// AbstractRadioTelescope class has implemented it. /// </summary> public bool ExecuteMoveRelativeAzimuth(RadioTelescopeAxisEnum axis, int speed, int position) { int positionTranslationAZ = 0, positionTranslationEL = 0; if (axis == RadioTelescopeAxisEnum.ELEVATION) { positionTranslationEL = position; } else if (axis == RadioTelescopeAxisEnum.AZIMUTH) { positionTranslationAZ = position; } else { return(false); } return(RadioTelescope.PLCDriver.relative_move(speed, (ushort)50, positionTranslationAZ, positionTranslationEL)); //return MinorResponseIsValid(RadioTelescope.PLCClient.RequestMessageSend(PLCCommandAndQueryTypeEnum.TRANSLATE_AZEL_POSITION, axis, speed, position)); }
public override bool Controled_stop(RadioTelescopeAxisEnum axis, bool both) { ushort[] data = new ushort[] { 0x4, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; if (both) { MCUModbusMaster.WriteMultipleRegisters(MCUConstants.ACTUAL_MCU_WRITE_REGISTER_START_ADDRESS, MESSAGE_CONTENTS_HOLD_MOVE); return(true); } else if (axis == RadioTelescopeAxisEnum.AZIMUTH) { MCUModbusMaster.WriteMultipleRegisters(MCUConstants.ACTUAL_MCU_WRITE_REGISTER_START_ADDRESS, data); return(true); } else if (axis == RadioTelescopeAxisEnum.ELEVATION) { MCUModbusMaster.WriteMultipleRegisters(MCUConstants.ACTUAL_MCU_WRITE_REGISTER_START_ADDRESS + 10, data); return(true); } return(false); }
/// <summary> /// return true if the RT has finished the previous move comand /// </summary> public bool finished_exicuting_move(RadioTelescopeAxisEnum axis) //[7] { var Taz = RadioTelescope.PLCDriver.GET_MCU_Status(RadioTelescopeAxisEnum.AZIMUTH); var Tel = RadioTelescope.PLCDriver.GET_MCU_Status(RadioTelescopeAxisEnum.ELEVATION); bool azFin = Taz[(int)MCUConstants.MCUStatusBitsMSW.Move_Complete]; bool elFin = Tel[(int)MCUConstants.MCUStatusBitsMSW.Move_Complete]; if (axis == RadioTelescopeAxisEnum.BOTH) { return(elFin && azFin); } else if (axis == RadioTelescopeAxisEnum.AZIMUTH) { return(azFin); } else if (axis == RadioTelescopeAxisEnum.ELEVATION) { return(elFin); } return(false); }
public override RadioTelescopeDirectionEnum GetRadioTelescopeDirectionEnum(RadioTelescopeAxisEnum axis) { return(driver.GetRadioTelescopeDirectionEnum(axis)); }
public override bool Start_jog(RadioTelescopeAxisEnum axis, int speed, bool clockwise) { throw new NotImplementedException(); }
public override bool Controled_stop(RadioTelescopeAxisEnum axis, bool both) { throw new NotImplementedException(); }
/// <summary> /// Checks to see if the motors are currently moving. /// </summary> /// <param name="axis">Azimuth, elevation, or both.</param> /// <returns>True if moving, false if not moving.</returns> public abstract bool MotorsCurrentlyMoving(RadioTelescopeAxisEnum axis = RadioTelescopeAxisEnum.BOTH);
/// <summary> /// get an array of boolens representiing the register described on pages 76 -79 of the mcu documentation /// does not suport RadioTelescopeAxisEnum.BOTH /// see <see cref="MCUConstants.MCUStatusBitsMSW"/> for description of each bit /// </summary> /// <param name="axis"></param> /// <returns></returns> public abstract bool[] GET_MCU_Status(RadioTelescopeAxisEnum axis);
public abstract bool Start_jog(RadioTelescopeAxisEnum axis, int speed, bool clockwise);
public override bool Controled_stop(RadioTelescopeAxisEnum axis, bool both) { return(driver.Controled_stop(axis, both)); }
public override bool Start_jog(RadioTelescopeAxisEnum axis, int speed, bool clockwise) { return(driver.Start_jog(axis, speed, clockwise)); }
/// <summary> /// Method used to request to start jogging one of the Radio Telescope's axes /// at a speed, in either the clockwise or counter-clockwise direction. /// /// The implementation of this functionality is on a "per-RT" basis, as /// in this may or may not work, it depends on if the derived /// AbstractRadioTelescope class has implemented it. /// </summary> public bool StartRadioTelescopeJog(RadioTelescopeAxisEnum axis, int speed, bool clockwise) { return(RadioTelescope.PLCDriver.Start_jog(axis, speed, clockwise)); //return MinorResponseIsValid(RadioTelescope.PLCClient.RequestMessageSend(PLCCommandAndQueryTypeEnum.START_JOG_MOVEMENT, axis, speed, clockwise)); }
public byte[] RequestMessageSend(PLCCommandAndQueryTypeEnum MessageType, params object[] MessageParameters) { byte[] NetOutgoingMessage = { 0x13, 0x0, PLCCommandAndQueryTypeConversionHelper.ConvertToByte(MessageType), 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; PLCCommandResponseExpectationEnum ResponseExpectationValue; switch (MessageType) { case PLCCommandAndQueryTypeEnum.TEST_CONNECTION: case PLCCommandAndQueryTypeEnum.GET_CURRENT_AZEL_POSITIONS: case PLCCommandAndQueryTypeEnum.GET_CURRENT_LIMIT_SWITCH_STATUSES: case PLCCommandAndQueryTypeEnum.GET_CURRENT_SAFETY_INTERLOCK_STATUS: { ResponseExpectationValue = PLCCommandResponseExpectationEnum.FULL_RESPONSE; break; } case PLCCommandAndQueryTypeEnum.CANCEL_ACTIVE_OBJECTIVE_AZEL_POSITION: case PLCCommandAndQueryTypeEnum.SHUTDOWN: case PLCCommandAndQueryTypeEnum.CALIBRATE: case PLCCommandAndQueryTypeEnum.CONTROLLED_STOP: case PLCCommandAndQueryTypeEnum.IMMEDIATE_STOP: { ResponseExpectationValue = PLCCommandResponseExpectationEnum.MINOR_RESPONSE; break; } case PLCCommandAndQueryTypeEnum.SET_CONFIGURATION: { ResponseExpectationValue = PLCCommandResponseExpectationEnum.MINOR_RESPONSE; int StartSpeedAzimuth = (int)MessageParameters[0]; int StartSpeedElevation = (int)MessageParameters[1]; int HomeTimeoutAzimuth = (int)MessageParameters[2]; int HomeTimeoutElevation = (int)MessageParameters[3]; NetOutgoingMessage[3] = 0x84; NetOutgoingMessage[4] = 0x00; NetOutgoingMessage[5] = 0x00; NetOutgoingMessage[6] = 0x00; NetOutgoingMessage[7] = 0x0; NetOutgoingMessage[8] = (byte)(StartSpeedAzimuth / 0xFFFF); NetOutgoingMessage[9] = (byte)((StartSpeedAzimuth >> 8) & 0xFF); NetOutgoingMessage[10] = (byte)(StartSpeedAzimuth & 0xFF); NetOutgoingMessage[11] = 0x0; NetOutgoingMessage[12] = (byte)(StartSpeedElevation / 0xFFFF); NetOutgoingMessage[13] = (byte)((StartSpeedElevation >> 8) & 0xFF); NetOutgoingMessage[14] = (byte)(StartSpeedElevation & 0xFF); NetOutgoingMessage[15] = (byte)(HomeTimeoutAzimuth >> 8); NetOutgoingMessage[16] = (byte)(HomeTimeoutAzimuth & 0xFF); NetOutgoingMessage[17] = (byte)(HomeTimeoutElevation >> 8); NetOutgoingMessage[18] = (byte)(HomeTimeoutElevation & 0xFF); break; } case PLCCommandAndQueryTypeEnum.SET_OBJECTIVE_AZEL_POSITION: { ResponseExpectationValue = PLCCommandResponseExpectationEnum.MINOR_RESPONSE; Orientation ObjectiveOrientation = (Orientation)MessageParameters[0]; Array.Copy(BitConverter.GetBytes(ObjectiveOrientation.Azimuth), 0, NetOutgoingMessage, 3, 8); Array.Copy(BitConverter.GetBytes(ObjectiveOrientation.Elevation), 0, NetOutgoingMessage, 11, 8); break; } case PLCCommandAndQueryTypeEnum.START_JOG_MOVEMENT: { ResponseExpectationValue = PLCCommandResponseExpectationEnum.MINOR_RESPONSE; RadioTelescopeAxisEnum AxisEnum = (RadioTelescopeAxisEnum)MessageParameters[0]; int AxisJogSpeed = (int)MessageParameters[1]; bool JogClockwise = (bool)MessageParameters[2]; switch (AxisEnum) { case RadioTelescopeAxisEnum.AZIMUTH: { NetOutgoingMessage[3] = 0x1; break; } case RadioTelescopeAxisEnum.ELEVATION: { NetOutgoingMessage[3] = 0x2; break; } default: { throw new ArgumentException("Invalid RadioTelescopeAxisEnum value seen while preparing jog movement bytes: " + AxisEnum.ToString()); } } NetOutgoingMessage[4] = 0x0; NetOutgoingMessage[5] = (byte)(AxisJogSpeed / 0xFFFF); NetOutgoingMessage[6] = (byte)((AxisJogSpeed >> 8) & 0xFF); NetOutgoingMessage[7] = (byte)(AxisJogSpeed & 0xFF); NetOutgoingMessage[8] = (byte)(JogClockwise ? 0x1 : 0x2); break; } case PLCCommandAndQueryTypeEnum.TRANSLATE_AZEL_POSITION: { ResponseExpectationValue = PLCCommandResponseExpectationEnum.MINOR_RESPONSE; RadioTelescopeAxisEnum AxisEnum = (RadioTelescopeAxisEnum)MessageParameters[0]; int AxisJogSpeed = (int)MessageParameters[1]; int position = (int)MessageParameters[2]; switch (AxisEnum) { case RadioTelescopeAxisEnum.AZIMUTH: { NetOutgoingMessage[3] = 0x1; break; } case RadioTelescopeAxisEnum.ELEVATION: { NetOutgoingMessage[3] = 0x2; break; } default: { throw new ArgumentException("Invalid RadioTelescopeAxisEnum value seen while preparing relative movement bytes: " + AxisEnum.ToString()); } } NetOutgoingMessage[4] = 0x0; NetOutgoingMessage[5] = (byte)(AxisJogSpeed / 0xFFFF); NetOutgoingMessage[6] = (byte)((AxisJogSpeed >> 8) & 0xFF); NetOutgoingMessage[7] = (byte)(AxisJogSpeed & 0xFF); if (position > 0) { NetOutgoingMessage[8] = 0x0; NetOutgoingMessage[9] = (byte)(position / 0xFFFF); NetOutgoingMessage[10] = (byte)((position >> 8) & 0xFF); NetOutgoingMessage[11] = (byte)(position & 0xFF); } else { NetOutgoingMessage[8] = 0xFF; NetOutgoingMessage[9] = (byte)((position / 0xFFFF) - 1); NetOutgoingMessage[10] = (byte)((position >> 8) & 0xFF); NetOutgoingMessage[11] = (byte)(position & 0xFF); } break; } default: { throw new ArgumentException("Illegal PLCCommandAndQueryTypeEnum value: " + MessageType.ToString()); } } NetOutgoingMessage[2] += (byte)(PLCCommandResponseExpectationConversionHelper.ConvertToByte(ResponseExpectationValue) * 0x40); // This is the expected response size of anything from the PLC (simulated or real), minor or full response. // See the TCP/IP packet contents google sheets file describing this under Wiki Documentation -> Control Room in the shared GDrive byte ExpectedResponseSize = (ResponseExpectationValue == PLCCommandResponseExpectationEnum.FULL_RESPONSE) ? (byte)0x13 : (byte)0x3; return(SendMessageWithResponse(NetOutgoingMessage, ExpectedResponseSize)); }
public override bool MotorsCurrentlyMoving(RadioTelescopeAxisEnum axis = RadioTelescopeAxisEnum.BOTH) { throw new NotImplementedException(); }
public override RadioTelescopeDirectionEnum GetRadioTelescopeDirectionEnum(RadioTelescopeAxisEnum axis) { throw new NotImplementedException(); }
/// <summary> /// Gets the direction that the specfied axis is moving. /// </summary> /// <param name="axis">Azimuth or elevation.</param> /// <returns>The direction that the specfied axis is spinning.</returns> public abstract RadioTelescopeDirectionEnum GetRadioTelescopeDirectionEnum(RadioTelescopeAxisEnum axis);
public override bool[] GET_MCU_Status(RadioTelescopeAxisEnum axis) { return(driver.GET_MCU_Status(axis)); }
public abstract bool Controled_stop(RadioTelescopeAxisEnum axis, bool both);
public override bool MotorsCurrentlyMoving(RadioTelescopeAxisEnum axis = RadioTelescopeAxisEnum.BOTH) { return(driver.MotorsCurrentlyMoving(axis)); }
/// <summary> /// Method used to request to start jogging the Radio Telescope's elevation /// at a speed (in RPM), in either the clockwise or counter-clockwise direction. /// </summary> public MovementResult StartRadioTelescopeJog(double speed, RadioTelescopeDirectionEnum direction, RadioTelescopeAxisEnum axis) { MovementResult result = MovementResult.None; // Return if incoming priority is equal to or less than current movement if ((MovementPriority.Jog - 1) <= RadioTelescope.PLCDriver.CurrentMovementPriority) { return(MovementResult.AlreadyMoving); } // We only want to do this if it is safe to do so. Return false if not if (!AllSensorsSafe) { return(MovementResult.SensorsNotSafe); } // If a lower-priority movement was running, safely interrupt it. if (RadioTelescope.PLCDriver.InterruptMovementAndWaitUntilStopped()) { return(MovementResult.StoppingCurrentMove); } // If the thread is locked (two moves coming in at the same time), return if (Monitor.TryEnter(MovementLock)) { RadioTelescope.PLCDriver.CurrentMovementPriority = MovementPriority.Jog; double azSpeed = 0; double elSpeed = 0; if (axis == RadioTelescopeAxisEnum.AZIMUTH) { azSpeed = speed; } else { elSpeed = speed; } result = RadioTelescope.PLCDriver.StartBothAxesJog(azSpeed, direction, elSpeed, direction); Monitor.Exit(MovementLock); } else { result = MovementResult.AlreadyMoving; } return(result); }