반응형

   

static class Ieee754Converter
{
    public static byte[] GetBytes(float value)
    {
        byte[] bytes = BitConverter.GetBytes(value);
        return bytes;
    }
    public static float ToSingle(byte[] bytes)
    {
        float value = BitConverter.ToSingle(bytes, 0);
        return value;
    }
}

 

예 : +7.282600E+01  <-> {0xE9} {0xA6} {0x91} {0x42}

 

byte[ ] temp = Ieee754Converter.GetBytes(3.141592f);
float value = Ieee754Converter.ToSingle(temp);
       

반응형
반응형

이전에 JSON을 이용하여 제어프로그램의 Recipe 파일의 저장과 불러오기 기능에 대해 포스팅 했었다. 

그런데 조금 사용하기 불편하고 코딩량이 많아서 다른 수단을 찾다가 YAML 이 최근에 설정파일 저장용으로 많이 사용된다는 것을 보고 사용해 보았다. 코딩량도 상당히 줄었고 무엇보다 항목을 추가하거나 제거할 때 코딩에서 수정해야 하는 부분이 많이 줄어서 현재 모든 프로그램에서 사용하고 있다. 

 

1. YAML 사용하기 위해 Nuget에서 YamlDotNet 을 먼저 설치한다. 

 

2. Yaml 데이타를 저장하거나 불러오기 위한 클래스 생성 : 다양한 종류의 설정항목에 대응하기 위해 generic class 형식으로 만듦

public class YamlControl<T>
{ 
    public bool SaveYaml(string FileName, T data)
    {
        bool result = true;

        try
        {
            var serializer = new SerializerBuilder().Build().Serialize(data);

            using StreamWriter sw = new StreamWriter(FileName);
            sw.Write(serializer);
        }
        catch
        {
            result = false;    
        }

        return result;
    }

    public bool LoadYaml(string FileName, ref T objectData)
    {
        bool result = true;

        try
        {
            var yaml = File.ReadAllText(FileName);
            objectData = new DeserializerBuilder().Build().Deserialize<T>(yaml);
        }
        catch
        {
            result = false;
        }            

        return result;
    }
}

 

3. 설정항목에 대한 클래스 생성 : 아래 클래스는 프로그램에 따라 변경해야 하며 아래 내용은 예시적으로 만든 임의의 클래스 

public class RecipeInform
{
    public BurnInParam burnInParam = new BurnInParam();
    public SweepMeasParam sweepMeasParam = new SweepMeasParam();

    public class BurnInParam
    {
        public bool Measurement { get; set; }
        public double Bias { get; set; }
        public double Step { get; set; }
    }
    
    public class SweepMeasParam
    {
        public double StartCurrent { get; set; }
        public double StopCurrent { get; set; }
        public double StepCurrent { get; set; }
    }
}

 

4. 사용방법 

항목 불러오기 

YamlControl<RecipeInform> yamlControl = new YamlControl<RecipeInform>();
string filename = string.Format("{0}{1}.yaml", Global.conditionFolder, comboCondition.Text);
RecipeInform recipe = new RecipeInform();
yamlControl.LoadYaml(filename, ref recipe);


항목 저장하기 

RecipeInform recipe = new RecipeInform();
recipe.burnInParam.Measurement = checkBurnInMeas.Checked;
recipe.burnInParam.Bias = double.Parse(textBiasCurrent.Text);
recipe.burnInParam.Step = double.Parse(textBurnInStepCurrent.Text);
recipe.sweepMeasParam.StartCurrent = double.Parse(textStartCurrent.Text);
recipe.sweepMeasParam.StopCurrent = double.Parse(textStopCurrent.Text);
recipe.sweepMeasParam.StepCurrent = double.Parse(textStepCurrent.Text);


string filename = string.Format("{0}{1}.yaml", Global.conditionFolder, comboCondition.Text);
YamlControl<RecipeInform> yamlControl = new YamlControl<RecipeInform>();
yamlControl.SaveYaml(filename, recipe) ;
반응형
반응형

 

    public class FML300 
    {
        private readonly SerialPort commPort ;
        private readonly ModbusSerialMaster modbusSerialMaster ;

        public FML300(ModbusSerialMaster modbusSerial)
        {
            modbusSerialMaster = modbusSerial;
        }
        //---------------------------------------------------------------------------
        public FML300(SerialPort serialPort)
        {
            commPort = serialPort ;
            modbusSerialMaster = ModbusSerialMaster.CreateRtu(commPort) ;
        }
        //---------------------------------------------------------------------------
        public FML300(string portNumber)
        {
            try
            {
                commPort = new SerialPort(portNumber, 38400) ;
                commPort.Parity = Parity.None;
                commPort.StopBits = StopBits.One;
                commPort.ReadTimeout = 100;
                commPort.WriteTimeout = 100;
                commPort.Open();

                modbusSerialMaster = ModbusSerialMaster.CreateRtu(commPort) ;
            }
            catch
            {
            }
        }
        //---------------------------------------------------------------------------
        public bool InstantaneousFlowRate(byte DeviceAddress, ref double FlowRate)
        {
            bool result = true ;

            try
            {
                var buffer = modbusSerialMaster.ReadInputRegisters(DeviceAddress, 3, 1);
                FlowRate = buffer[0] ;
            }
            catch
            {
                result = false ;
            }

            return result ;
        }
        //---------------------------------------------------------------------------
        public bool FlowTemperature(byte DeviceAddress, ref double Temperature)
        {
            bool result = true ;    

            try
            { 
                var buffer = modbusSerialMaster.ReadInputRegisters(DeviceAddress, 4, 1) ;
                Temperature = buffer[0] ;
                if(Temperature > 6000) Temperature = 0;     // 물이 흐르지 않으면 온도가 큰값이 읽혀진다. 
            }
            catch
            {
                result = false ;
            }

            return result ;
        }
        //---------------------------------------------------------------------------
        public int FlowRateAndTemperature(byte DeviceAddress, ref double FlowRate, ref double Temperature)
        {
            int result = 0 ;    

            try
            { 
                var buffer = modbusSerialMaster.ReadInputRegisters(DeviceAddress, 1, 4) ;

                FlowRate = (double)buffer[1] / 100.0 ;
                Temperature = (double)buffer[2] / 10.0 ;

                if(Temperature > 6000) Temperature = 0;     // 물이 흐르지 않으면 온도가 큰값이 읽혀진다. 
            }
            catch
            {
                result = -1 ;
            }

            return result ;
        }
        //---------------------------------------------------------------------------
    }
반응형
반응형

 

    public class RodemSeries
    {
        private SerialPort commPort;
        public double InputVoltage { get; }
        public double OutputVoltage { get; }
        public double Temperature { get; }
        public int BlackOut { get; }        // 0:No, 1:Yes
	    public int LowBattery { get; }      // 0:No, 1:Yes

        public RodemSeries(SerialPort CommPort)
        {
            commPort = CommPort;
        }
        //---------------------------------------------------------------------------
        public bool Initialize(string ModelName)
        {
            bool result = false ;
	        byte[] sendBuffer = new byte[] {(byte)'I', 0x0d} ;

            try
            {
                commPort.Write(sendBuffer, 0, sendBuffer.Length);
                Thread.Sleep(500);

                if(commPort.BytesToRead > 0)
                {
                    byte[] readBuffer = new byte[commPort.BytesToRead + 5];
                    commPort.Read(readBuffer, 0, commPort.BytesToRead);
                    string str = Encoding.Default.GetString(readBuffer);
                    result = str.Contains(ModelName);
                }
            }
            catch 
            { 
                result = false; 
            }

            return result ;
        }
        //---------------------------------------------------------------------------
        public bool ReadStatus()
        {
            bool result = true;
	        byte[] sendBuffer = new byte[] {(byte)'Q', (byte)'1', 0x0d} ;

            try
            {
                commPort.Write(sendBuffer, 0, sendBuffer.Length);
                Thread.Sleep(500);

                if(commPort.BytesToRead > 0)
                {
                    byte[] readBuffer = new byte[commPort.BytesToRead + 5];
                    commPort.Read(readBuffer, 0, commPort.BytesToRead);

                    if(readBuffer[0] != (byte)'(') result = false;
                    else
                    {
                        result = StatusInformation(readBuffer);    
                    }                    
                }
                else
                {
                    result = false;
                }
            }
            catch 
            { 
                result = false; 
            }

            return result;
        }
        //---------------------------------------------------------------------------
        private bool StatusInformation(byte[] Buffer)
        {
            bool result = true;

            try
            {
                string str = Encoding.Default.GetString(Buffer);
                string[] data = str.Split(' ');

                OutputVoltage = double.Parse(data[2]) ;
                Temperature = double.Parse(data[6]) ;

                BlackOut = Buffer[38] - 0x30;
                LowBattery = Buffer[39] - 0x30;

                if (BlackOut > 1 || BlackOut < 0) BlackOut = 0;
                if (LowBattery > 1 || LowBattery < 0) LowBattery = 0;
            }
            catch
            {
                result = false;
            }

            return result;
        }
        //---------------------------------------------------------------------------
    }
반응형
반응형

국내 나이스 쿨의 칠러 제어를 위한 코드 입니다. RS232통신을 통해 제어를 합니다. 

Modbus RTU 방식으로 처리하고 라이브러리는 NModbus4를 사용하였습니다. 

NModbus4 는 Nuget을 통해 설치하시면 됩니다. 

 

 

/****************************************************************************************************
     * Device : Chiller(CM SERIES)
     * Manufacture : NiceCool
     * Devicce Interface : RS232(Modbus RTU)
     * Version : 1.0.0
     * Program : Sihwan Kim
     *****************************************************************************************************/
    public class NiceCool_CMSeries 
    {
        public bool Active { get; set; } = false;
        public int ReadTimeout
        {
            set { modbusSerialMaster.Transport.ReadTimeout = value; }
            get { return modbusSerialMaster.Transport.ReadTimeout; }
        } 

        public int WriteTimeout
        {
            set { modbusSerialMaster.Transport.WriteTimeout = value; }
            get { return modbusSerialMaster.Transport.WriteTimeout; }
        } 

        private byte address;
        private SerialPort commPort ;
        private ModbusSerialMaster modbusSerialMaster ;

        public NiceCool_CMSeries(byte Address, ModbusSerialMaster modbusSerial)
        {
            address = Address;
            modbusSerialMaster = modbusSerial;
        }
        //---------------------------------------------------------------------------
        public NiceCool_CMSeries(byte Address, SerialPort serialPort)
        {
            address = Address;
            commPort = serialPort ;
            modbusSerialMaster = ModbusSerialMaster.CreateRtu(commPort) ;
        }
        //---------------------------------------------------------------------------
        public NiceCool_CMSeries(byte Address, string portNumber)
        {
            address = Address;

            try
            {
                commPort           = new SerialPort() ;
                commPort.PortName  = portNumber ;
                commPort.BaudRate  = 4800;
                commPort.Parity = Systehttp://m.IO.Ports.Parity.Even;
                commPort.Open();

                modbusSerialMaster = ModbusSerialMaster.CreateRtu(commPort) ;
            }
            catch
            {
            }
        }
        //---------------------------------------------------------------------------
        public bool Initialize(bool control)
        {
            bool result = true ;
            double temp = 0;

            ReadTimeout = 300; 
            WriteTimeout = 300;

            commPort.ReadTimeout = 300;
            commPort.WriteTimeout = 300;

            if (control) result = WaterTemperature(ref temp) ;

            return result;
        }
        //---------------------------------------------------------------------------
        public bool WaterTemperature(ref double Temperature)
        {
            bool result = true;

            try
            {
                var value = modbusSerialMaster.ReadHoldingRegisters(address, 259, 1) ;
                Temperature = value[0] / 10.0 ;
            }
            catch
            {
                result = false ;
            }

            return result;
        }
        //---------------------------------------------------------------------------
        public void SetWaterTemperature(double Temperature)
        {
            ushort setTemp = (ushort)(Temperature * 10) ;

            try
            { 
                modbusSerialMaster.WriteSingleRegister(address, 271, setTemp) ;
            }
            catch { }
        }
        //---------------------------------------------------------------------------
        public bool Run(bool Status)
        {
            bool result = true;
            
            try
            { 
                ushort action = 0 ;

                if(Status == true) action = 257 ;
                else action = 256 ;

                modbusSerialMaster.WriteSingleRegister(address, 270, action) ;
                Active = Status ;
            }
            catch
            {
                result= false ;
            }

            return result ;
        }
        //---------------------------------------------------------------------------
        public bool WaterFlow(ref double FlowValue)
        {
            bool result = true;

            try
            { 
                var value = modbusSerialMaster.ReadHoldingRegisters(address, 266, 1) ;
                FlowValue = value[0] / 10.0 ;
            }
            catch
            {
                result = false ;
            }

            return result;
        }
    }

반응형
반응형

 

소코반 게임을 WPF 버젼으로 수정해서 올립니다. 아직 WPF를 공부중이라 MVVM 은 사용을 하지 않고 제작을 하였습니다.

코드는 지속적으로 수정을 진행할 예정입니다. 

소스 코드는 아래 Git에서 다운 받으시면 됩니다. 

 

https://github.com/Sihwan-Kim/PushPush.git

 

아래 파일은 맵화일과 Config파일 입니다. 실행파일이 있는 곳에 넣으시면 됩니다. 

stage.zip
0.00MB

 

Winform 버전의 알고리즘은 그대로 사용하였고 기능적인 부분이 조금 수정되었습니다. 

1. 윈폼 버전에서는 맵의 크기가 10 x 10으로 고정하였지만 WPF 버전에서는 크기를 동적으로 수정할 수 있도록 하였습니다.

2. 윈도우의 크기가 변경되면 맵이 항상 중앙에 위치 하도록 하였습니다. 

 

 

 

반응형
반응형

        private static Array ResizeArray(Array arr, int[] newSizes)
        {
            if(newSizes.Length != arr.Rank)
            {
                throw new ArgumentException("arr must have the same number of dimensions " +
                                            "as there are elements in newSizes", "newSizes");
            }

            var temp = Array.CreateInstance(arr.GetType().GetElementType(), newSizes);
            int length = arr.Length <= temp.Length ? arr.Length : temp.Length;
            Array.ConstrainedCopy(arr, 0, temp, 0, length);

            return temp;
        }

//----------------------------------------------------------------------------------------------------------------

public int[,] array = new int[2, 2] ;     // 2 x 2 배열 생성 

array  = (int[,])ResizeArray( array  , new int[] {12, 3}) ;    // 12 x 3 형식으로 변경 

 

 

반응형
반응형

C# 의 winform 으로 소코반(Sokoban) 게임을 만들어 보았습니다. 

아마 프로그램 배우시는 분들이 가장 쉽게 만들어 볼 수 있는 게임 프로그램이 아닐까 합니다. 

 

프로그램의 형태는 아래 그림과 같습니다.

 

현재 기본적인 게임 알고리즘은 구현이 되어 있고 조금씩 기능을 업데이트 하고 있는 중입니다. 

소스는  Github 에 올려 두었습니다. 

 

https://github.com/Sihwan-Kim/Sokoban.git

 

코드는 계속 업데이트할 계획입니다. 

 

반응형

+ Recent posts