[작성자:] 이대원

  • HSM을 활용한 레고 장난감 만들기

    HSM을 활용한 레고 장난감 만들기

    기억하기 위해서 기록해 놓음..

    처음 다이어그램인데..수정.
    12113378_1289445931071053_7620380557359358782_o

    수정 다이어그램은 아래와 같다.
    20160908_225320

    기존 대비 S11을 지워 버렸다. S10에서 S11로 transiton이 발생할 때, 모터 동작이 끝나기 때문에 굳이 S11을 만들 필요가 없다. self transition으로 처리했다. state machine을 내가 제대로 이해하고 있는지 모르겠으나..

    S13에서도 self transition을 추가 했는데, 회전 동작시 장애물을 완전하게 피했는지를 확인하기 위해서이다. S13에서 이벤트를 다시 한번 확인하고, 장애물에 걸리면 전진동작 없이 회피 동작을 하도록 했다.

    가장 고민했던 부분은 S0은 event driven program이고 S1은 data driven program 방식으로 접근해야 할 것 같은데, 모든 ir센서로 읽어 들이는 모든 데이터를 event로 분류하기가 힘들었다. 이벤트로 설정하려면 배타적 관계도 확인해 봐야 하는데, 버튼 눌림여부 * 버퍼의 수치별 이벤트를 한개의 event로 처리하려면 경우의 수가 너무 많았다. 쿨하게 evnet는 아래와 같이 몇가지 경우만 잡았다. 나머지는 S1에 들어갔으므로 대략 무시하기로 했다.

    package hsm;
    
    import lejos.hardware.Button;
    
    public class Event {
    	  
    	  public enum mEvent {EnterPressed,DownPressed,GapIsWide,GapIsNarrow,Nothing};
    	  
    	  //Ir센서를 읽기 위한 부분..
    	  private float irValue;
    	  
    	  public Event(float tmp){
    		  this.irValue = tmp;
    	  }
    	 /* 
    	  public void setEventBuffer(float value){
    		  this.irValue = value;
    	  }
    	  */
    	  
    	  public mEvent getID(){
    		  
    		  mEvent thisEvent = mEvent.Nothing;
    		  
    		  //버퍼에서 데이터를 읽어 들임 
    
    		  if(Button.ENTER.isDown() == true)
    			  return mEvent.EnterPressed;
    
    		  if(Button.DOWN.isDown() == true)
    			  return mEvent.DownPressed;
    		  
    		  if(irValue > 10)
    		  	return mEvent.GapIsWide;
    		  
    		  if(irValue <= 10)
    			  return mEvent.GapIsNarrow;
    		 		  
    		  return thisEvent;
    	  }
    	  
    	  
    
    
    }

    일단 S1에 들어가면, irRead -> ir 버퍼 가공 -> 모터 동작의 방식으로 처리했는데, 이 방법도 좋지 않았다. 각 state별 process가 다른데, thread로 돌리면 이를 구분할 수 없게 된다. 따라서 아래와 같이 수정했다.

    S10,S13에서만 irRead 동작, S10,S12,S13에서는 모터 동작, 각 transition에 따른 버퍼값 수정..

    S0에서는 버튼이 눌림만 감시하기 때문에 event driven programming으로 접근했다.

    hsm의 c++ -> java 이식은 인터넷의 코드를 그대로 사용했다.
    hsm의 구조는 대략 아래와 같다.

    package hsm;
    
    import mypackage.IrBufferv2;
    import mypackage.MotorData;
    
    public class myHsmForLego extends Hsm{
    	private MotorData mMotorData;
    	
    	Runnable myIrRun;
    	Runnable myMotorRun;
    	Runnable myProcessRun;
    
    	
    
    
    	public myHsmForLego(MotorData motor,Runnable irTh, Runnable motorTh, Runnable ProcessTh){
    		this.mMotorData = motor;
    		
    		//thread를 전달하기 위한 부분
    		this.myIrRun = irTh; 
    		this.myMotorRun = motorTh;
    		this.myProcessRun = ProcessTh;
    
    	}
    	
    	@Override
    	public void init() {
    		// TODO Auto-generated method stub
    		System.out.print("Top-INIT;" );
    	    
    	    //초기화시 모터 목표를 0으로 설정
    		super.init();
    	}
    
    	@Override
    	public State fireInit() {
    		// TODO Auto-generated method stub
    	    System.out.print("INIT>>s;" );
    		return s0;
    	}
    
    	@Override
    	public void enter() {
    		// TODO Auto-generated method stub
    	    System.out.print("ENTRY>>s;" );
    
    	}
    	
    	@Override
    	public State fireEvent(Event e) {
    		// TODO Auto-generated method stub
    		return getParent();
    	}//fireEvent
    
    	@Override
    	public void exit() {
    		// TODO Auto-generated method stub
    	    System.out.print("EXIT<<s;" );
    	    System.out.print("\n");
    
    
    	}
    	
    	Hsm s = this;                 // This is just alias of current instance
    
    	
    	
    	State s0 = new State(s){
    		@Override
    		public State fireEvent(Event e) {
    			// TODO Auto-generated method stub
    			switch(e.getID())
    			{
    				case EnterPressed :
    					transition(s1);
    					return null;
    
    				default :
    					  break;
    			}
    			
    			return getParent();
    		}//fireEvent
    		
    		@Override
    		public State fireInit() {
    			// TODO Auto-generated method stub
    		    System.out.print("INIT>>s0;" );
    			return null;
    		}
    
    		@Override
    		public void enter() {
    			// TODO Auto-generated method stub
    		    System.out.print("ENTRY>>s0;" );
    			
    		}
    
    		@Override
    		public void exit() {
    			// TODO Auto-generated method stub
    		    System.out.print("EXIT<<s0;" );
    		    System.out.print("\n");
    		
    		}
    		
    	};//sate s0
    	
    	State s1 = new State(s){
    
    		@Override
    		public State fireInit() {
    			// TODO Auto-generated method stub
    		    System.out.print("INIT>>s1;" );
    			return s10;
    		}
    
    		@Override
    		public void enter() {
    			// TODO Auto-generated method stub
    		    System.out.print("ENTRY>>s1;" );
    	
    		}
    
    		@Override
    		public State fireEvent(Event e) {
    			// TODO Auto-generated method stub
    			switch(e.getID())
    				{
    					case DownPressed :
    						transition(s0);
    						return null;
    
    					default :
    						  break;
    				}
    			return null;
    		}
    
    		@Override
    		public void exit() {
    			// TODO Auto-generated method stub
    		    System.out.print("EXIT<<s1;" );
    		    System.out.print("\n");
    				
    		}
    		
    	};//state s1;
    	
    	
    
    	State s10 = new State(s1){
    
    		@Override
    		public State fireInit() {
    			// TODO Auto-generated method stub
    		    System.out.print("INIT>>s10;" );
    			return null;
    		}
    
    		@Override
    		public void enter() {
    			// TODO Auto-generated method stub
    			// IR 센서값을 버퍼에 저장..
    			// 이벤트를 판단할 수 있게됨..
    			myIrRun.run();
    		    System.out.print("ENTRY>>s10;" );
    	
    		}
    
    		@Override
    		public State fireEvent(Event e) {
    		
    			// TODO Auto-generated method stub
    			switch(e.getID())
    			{
    			case GapIsWide :
    				//모터 이동부분 추가.
    				// 아래 process run은 삭제필요..
    				// thread를 인수로 줄수 없음..
    				//myProcessRun.run();
    				mMotorData.storeTargetDistance(10, 10);
    				myMotorRun.run();
    				
    				//seft transition
    				transition(s10);
    				return null;
    
    			case GapIsNarrow :
    				mMotorData.storeTargetDistance(-50, -50);
    				myMotorRun.run();
    
    				transition(s12);
    				return null;
    
    			default :
    				break;
    			
    			}
    			return getParent();
    		}//fireEvent
    
    		
    		@Override
    		public void exit() {
    			// TODO Auto-generated method stub
    		    System.out.print("EXIT<<s10;" );
    			System.out.print("\n");
    
    		}
    			
    	};//state s10
    
    	
    	/* 아래 부분은 삭제..2016.09.08
    	State s11 = new State(s1){
    
    		@Override
    		public State fireInit() {
    			// TODO Auto-generated method stub
    		    System.out.print("INIT>>s11;" );
    			return null;
    		}
    
    		@Override
    		public void enter() {
    			// TODO Auto-generated method stub
    		    System.out.print("ENTRY>>s11;" );
    			
    		}
    
    		@Override
    		public State fireEvent(Event e) {
    			// TODO Auto-generated method stub
    			switch(e.getID())
    			{
    			case GapIsWide:
    				//seft transition
    				//모터 이동부분 추가.
    				myIrRun.run();
    				myProcessRun.run();
    				myMotorRun.run();
    				transition(s11);
    				//모터 이동부분 추가.
    				return null;
    
    			case GapIsNarrow:
    				//모터 이동부분 추가.
    				mMotorData.storeTargetDistance(-10, -10);
    				myMotorRun.run();
    
    				transition(s12);
    				return null;
    
    			default :
    				break;
    			
    			}
    			
    			return getParent();
    		}//fireEvent
    
    		@Override
    		public void exit() {
    			// TODO Auto-generated method stub
    			System.out.print("EXIT<<s11;" );
    			System.out.print("\n");
    		}
    			
    	};//State s11
    	*/
    	
    	State s12 = new State(s1){
    
    		@Override
    		public State fireInit() {
    			// TODO Auto-generated method stub
    		    System.out.print("INIT>>s12;" );
    
    			return null;
    		}
    
    		@Override
    		public void enter() {
    			// TODO Auto-generated method stub
    		    System.out.print("ENTRY>>s12;" );
    		}
    
    		@Override
    		public State fireEvent(Event e) {
    			// TODO Auto-generated method stub
    			//모터 이동부분 추가.
    			mMotorData.storeTargetDistance(50, -50);
    			myMotorRun.run();
    
    			transition(s13);
    			return getParent();
    
    		}//fireEvent
    
    		@Override
    		public void exit() {
    			// TODO Auto-generated method stub
    			System.out.print("EXIT<<s12;" );
    			System.out.print("\n");
    
    		}
    		
    		
    	};//State s12
    
    	State s13 = new State(s1){
    
    		@Override
    		public State fireInit() {
    			// TODO Auto-generated method stub
    			System.out.print("INIT>>s13;" );
    
    			return null;
    		}
    
    		@Override
    		public void enter() {
    			// TODO Auto-generated method stub
    			// 충분하게 돌았는지 확인.
    			myIrRun.run();
    			System.out.print("ENTRY>>s13;" );
    
    			
    		}
    
    		@Override
    		public State fireEvent(Event e) {
    			// TODO Auto-generated method stub
    			switch(e.getID())
    				{
    					case GapIsWide :
    						//모터 이동부분 추가.
    						// 아래 process run은 삭제필요..
    						// thread를 인수로 줄수 없음..
    						//myProcessRun.run();
    						transition(s10);
    						return null;
    
    					case GapIsNarrow :
    						//충분하게 돌지 못해더 더 돌아야 된단고 판단.
    						mMotorData.storeTargetDistance(50, -50);
    						myMotorRun.run();
    						transition(s10);
    						return null;
    
    					default :
    						break;
    
    			}
    			return getParent();
    		}//fireEvent
    
    		@Override
    		public void exit() {
    			// TODO Auto-generated method stub
    			System.out.print("EXIT<<s13;" );
    			System.out.print("\n");
    
    			
    		}
    
    		
    	};//State 13
    
    
    		
    }//myHsmForLego
    

    다음에는 iR센서에 모터를 달아서 한바퀴 돌려보고 몇도로 움직여야 판단까지 하고 싶으나, 갈길이 멀어 보인다. 일단 이걸 다 뜯을 생각을 하니 머리가 아프다..한번 뜯으면 다시 조립 못할 것 같다..
    20160908_232920

  • mysql을 사용한 견적 산출 방법

    필요 조건..
    1. 최소 아이템을 입력으로
    2. 업데이트는 빈번하게..
    3. 한번 입력한 아이템은 다른 곳에서 사용할 수 있도록..

    임시 테이블을 만들어서, (각 경우에 따른, 주제어반/보조제어반+메이커 조합)
    어느 아이템이 들어갈지 정함..
    이 임시 테이블에 수량에 대한 항목이 정해져 있어야 됨..

    모든 테이블에서 해당하는 아이템을 뽑아내면, 사용 가능할 것 같음..

    select * from `cost`;
    
    create temporary table `주제어반_ABPLC` (`ItemID` int, `수량` int);
    
    
    #제어반을 구성하기 위한 ID/수량 매핑
    
    insert into `주제어반_ABPLC` values (7,1),(13,5),(17,1),(20,3);
    
    select * from `주제어반_ABPLC`;
    
    drop temporary table `주제어반_ABPLC`;
    
    
    #각 항목에서 해당하는 ITEM, 수량을 산출하기 위한 식..
    
    select '주제어반',`cost`.`모델명`, `cost`.`세부사양`,`cost`.`제작사`,`주제어반_ABPLC`.`수량`,`cost`.`개당가격` from `cost`
     inner join `주제어반_ABPLC` on `cost`.`ItemID`=`주제어반_ABPLC`.`ItemID`;

    단점은 만들 임시 테이블이 너무 많음..

  • Gen8 Microserver cpu 업그레이드 완료

    멕시코에 있을때, 주문해 놓은 cpu를 오늘 장착했다. 주문후, 일주일이면 판매자에게 금액이 자동으로 지급되었다. 오늘 이 cpu가 안되었다면 돈 날렸을 것이다.

    전에 스크랩해 놓은 사이트를 방문해서 그대로 따라했다. 그 문서에는 cpu 교체에 대한 내용이 별로 없었다. 메인보드를 빼고, 펌웨어 업데이트 등, 총 약 두시간정도 걸렸다.
    보드 거의 부실뻔했다!!1

    1. bios, ilo를 최신 버전으로 업데이트..ok
    bios 업데이트를 usb로 하는줄 알았는데, 이럴수가.. hp에서 iLO라고 서버를 점검할 수 있는 통로가 있다. 웹브라우저로 연결하면 이것저것 다 할수 있는데, 여기에 bios, iLO의 펌웨어 업데이트가 가능하다. 와~~ 이걸 모르고 bios를 usb 저장장치에 옮겨 부팅을 하려 했다..모니터 연결하고. 키보드 연결하고..–;

    2. 메인보드를 케이스에서 뺀다.
    망할. CPU는 보드 중앙에 조립되어 있어, 보드를 빼지 않고는 분리할 수 없다. 보드를 밖으로 빼야 되는데, 여러 케이블들이 걸려있다. 직관적으로 어떻게 빼는지 알수있는 케이블과 그렇지 않은 케이블이 있다. 특히4 f-io라고 적혀있는 케이블..양쪽에는 핀이 아니라

    CPU를 빼려면 메인보드?를 케이스에서 빼내야 되는데, 안에 케이블들이 걸린 부분이 있다. 그걸 다 떼내어야 되는데, 잘 안빠진다. 무슨 케이블인지도 모르겠고..대충 빠지는데, F-IO인가로 표시된 케이블이 있다. 양쪽 끝이 핀이라서 살살했는데,그게 아니다. 양쪽끝에 힘을 줘야 빠진다. 부서질까봐 한참 고민했다.

    3. CPU 교체
    거대한 방열판이 있는데, 그 안에 CPU가 있다. 방열판은 볼트 4개를 풀러 뺀다. 뽑기 좋아보이는 나사가 있길래, 살살 돌려주었더니, 딱 소리와 함께 CPU 고정하는 장치가 분리되었다!!! 나사산이 안나간게 다행이지. thermal grease를 발라주고, CPU를 고정한다. 레버를 누른다음에 아까 볼트를 끼는줄 알았으나, 아니다. 볼트를 고정후 레버를 두번 누르면 고정장치가 볼트 안쪽으로 들어가게 되어있다. 구입한 CPU는 벌크라고 팔았는데, 아마 중고를 판듯 하다. 안에 써멀 그리즈 자국이 남아있었다.

    4. 조립..
    역순으로 조립하면 된다…

    5. 와!!!엄청 빠르다?? plex mediaserver를 돌려보니, 역시 빠름이 느껴진다..다만 전기료가 얼마나 나올지 걱정이다.cpu_screen

  • 워드프레스 플러그인 업데이트 및 권한설정

    플러그인 업데이트를 위해서는 워드 프레스의 권한을 바꿔줘야 한다.

    셋업시 사용자/그룹을 웹서비스 유저로 설정하고…

    chown www-data:www-data  -R * # Let Apache be owner
    find . -type d -exec chmod 755 {} \;  # Change directory permissions rwxr-xr-x
    find . -type f -exec chmod 644 {} \;  # Change file permissions rw-r--r--

    설정이 완료되면, 보안을 이유로..아래와 같이 설정한다..

    chown <username>:<username>  -R * # Let your useraccount be owner
    chown www-data:www-data -R wp-content/ # Let apache be owner of wp-content
    #wordpress root에서
    chgrp www-data *

    wp-content는 www-data가 소유자로 그대로 둬야 한다. wp-content의 하부 디렉토리 권한을 안바꾸면 파일 업로드, 수정이 안된다.

    http://stackoverflow.com/questions/18352682/correct-file-permissions-for-wordpress

  • 자연은 왜 이런 선택을 했을까?

    자연은 왜 이런 선택을 했을까?

    자연은 왜 이런 선택을 했을까?
    isbn : 8996537144

    상쾌한 일요일..한 10시간 넘게 잤나? 나갈데도 없어 빌려 놓았던 책을 다시 봣다.멕시코.이제, 한주 남았다.. 이런 책들은 한번 읽으면 좋은데, 남는게 별로 없다. 단편적인 지식을 기억해서 머 쓸데도 없고..

    그래도 정리를 하기 위해서 목차를 참조한다.
    1장 인류와 동물 이야기
    2장 생명의 유희에 관하여
    3장 인류는 어떻게 환경을 변화시키는가?
    4장 스스로 변화하는 자연

    이 목차를 보니, 내용이 전혀 기억이 안난다.

    1장에서는 인류와 동물들이 지금까지 진화한 이야기를 한다. 내용중, 노동은 인간만 한다고 한다. 노동자는 위대하다. 자본가는 더 위대하다?? 장시간 일을 하기위해서는 냉각 시스템이 필수적인다. 동물들은 가죽으로 덮혀 있어, 냉각을 제대로 못한다. 인간이 땀샘으로 적절한 냉각을 하여 몸이 지속적으로 일할 수 있다. 덤으로 머리카락은 단백질의 배출구라고..왜 마약검사를 할때 머리카락을 뽑는지 알것 같다.

    2장 생명의 유희에 관하여
    주로 가축에 대한 내용이다. 말, 소, 돼지, 개를 인류가 서로의 필요에 의해서 가까워졌다고 한다. 흥미로운 점은 양, 소, ??가 인간과 식량과 경쟁을 안해, 이 3개만 기르고 더이상 가축으로 키울 짐승을 안찾았다고 한다. ㅋㅋㅋ대항해 시대의 삼각무역??

    3장, 4장은 제대로 안읽어서 무슨 내용인지 모르겠다. 산소가 과거 몇만년?숫자에 약해서 몇년인지는 모르겠으나, 한동안 쓰레기였다나..이 쓰레기를 사용할 줄 아는 미생물?생물이 나와서 비로소 유용한 자원으로 변했단다.

    열역학에서는 내연기관의 근본 원리는 엔진 안과 주변의 온도차라고 한다. 엔진이 과열되지 않기 위해서 적절한 냉각장치가 필수이다. 이를 인류에 적용하면 어떨까? 효율이 좋은 엔진을 만들기 위해서 각 메이커별로 경쟁을 한다. 과거 인간과 동물들이 지구의 패권을 놓고 다툴때, A사에서 만든 미친 효율의 엔진으로 다른 동물들을 제압했을것 같다. 여기서 A사는 신? 이런 관점을 유지하면, 인간과 기계는 결국 다를게 없다..우리는 모두 같은 형제들…낼부터 쇳덩이들한테 잘해줘야 겠다..

    요즘들어 갑자기 문제제기가 되는 유전자 조작 식품에 대해서 생각해본다. 언론에서는 GMO가 몸에 어떤 영향을 미치는지 검증을 안됬다고 까고 있다. 그러나 옥수수, 밀, 바나나?? 몇개의 blockbuster 식품들이 이미 장기간에 걸쳐 유전자가 조작되었다. 기술의 발달로 시행 빈도가 잦아지고, 효과가 극적으로 보인다. 고대의 농부역시 유전자 조작을 했는데, 몇 세대에 시행되었고 효과도 미비했다. 인간의 몸이 과거에는 식품의 진화속도에 충분히 적응을 해서 괜찮다? 아니라고 본다. 게다가 자연에서도 유전자가 섞는 행위가 많이 일어고 이 또한 유전자 조작이다. 자연은 괜찮고 사람이 하는 것은 안된다??자연산은 되고 양식은 안된다?

    유전자 조작보다는 소량품종이 다수의 지역에 재배되는 현상을 걱정해야 한다. 인간이 원하는 특성만 가진 식물만 재배된다면, 향후 급격한 환경변화에 적응을 못해 멸종될 것이다. 기업의 특성상 최소의 노력으로 최대의 이익을 추구하는데 이를 경계해야한다.

    미래 인간의 어떨지도 생각해본다. 자연적으로, 우연이든 인류 1개의 종이 대부분의 지구를 점령할 수 있었고, 인간이란 어디에서나 신체적, 정신적 능력이 비슷하다. 만약 진화가 급격히 일어난다면 우리는 어디까지를 인류라고 할 수 있을까? 머리에 뿔이 달렸거나, 꼬리가 있어도 인간이라고 할 수 있는가? 이에 대비해서 유전자 조작 기술을 어디까지 허용하고, 표준 인류?에 대한 사회적 합의도 했으면 한다.

    인공지능과, 유전자 개조에 대해서도 생각해본다. 현재 상태는 스타크래프트의 저그 대 프로토스의 대결구도이다. 인공지능이 특이점을 넘으면 인류를 지배한다고 한다고 난리다. 진화도 어느 특별한 폭발점이 있을 것이다. 현재 인류과 과거 공룡이 동일한 조상에서 나왔다고 하면, 진화의 능력은 대단하다. 게다가 이미 수많은 생물들이 검증을 했다. 우리가 유전자에 대해서 어느정도 이해했을때, 저그가 프로토스를 씹어먹을 것이다. 맨땅의 삽질보다 모방이 훨씬 쉬우니까..

    아래는…생물의 다양성을 그림으로 표시한 도표이다. 인상적이어서 기록해 놓는다..
    다양성비교표
    가운대 큰 그림은 딱정벌레이고, 왼쪽에 보면 코끼리로 표시된 포유류를 볼 수 있다.

    책에 보면..대형 동물의 멸종은 필수라는데, 윤회할 수 있도록 몸의 원자들에게 잘 대해줘야겠다. 내가 죽더라도 다른 우주에서 영생할 수 있기를…