레이블이 Arduino인 게시물을 표시합니다. 모든 게시물 표시
레이블이 Arduino인 게시물을 표시합니다. 모든 게시물 표시

2019년 4월 22일 월요일

Arduino(아두이노) RS-422(RS-485)로 스케치 전송하기. [작성중]



우선 Arduino 스케치를 전송 할때는 RS-232에서 Rx,Tx,DTR,GND 4선을 사용합니다.(일반적인 RS-232통신에서는 DTR을 안쓰고 3선을 연결하죠.)

송,수신 선이 나눠져 있으니 전이중(Full-duplex) 통신이 가능합니다.



그리고 RS-422에 경우 Rx,Tx 에 해당하는 선이 +,- 로 나눠서 RX+,RX-, TX+,TX- 로 4선을 사용해서 노이즈에 강하게 설계가 되었습니다.

송,수신 선이 나눠져 있으니 전이중(Full-duplex) 통신이 가능합니다.

그리고 추가로 RS-485에 경우 RS-422에서 RX+,TX+ 와 RX-,TX- 를 묶어서 2선을 사용 합니다.

송,수신 선이 합쳐져 있으니 반이중(Half-duplex) 통신만 가능합니다.

2선을 사용하는 장점이 있지만 송,수신 선이 서로 묶에 있어서 이를 동시에 처리 할 수는 없어서 소프트웨어적으로 동기를 잡아 줘야 합니다.



RS-485 Driver 는 소프트웨어적으로 DE, RE 단자를 제어해 줘야 합니다. (송신 할때 High를 주고, Low 상태에서는 수신만 가능 합니다.)

RS-485 Driver 를 사용해서 RS-422을 구현 하려며 칩을 2개 사용 해서 칩 하나는 항상 수신, 다른 하나는 항상 송신으로 사용 하면 되겠죠.

그럼 Arduino에 스케치 전송을 위해서 DTR도 RS-485 Driver 를 사용해서 DTR+,DTR-로 변환해서 처리를 한다면 DTR시그널이 살아나므로 노이즈에 강한 시그널을 사용할수 있습니다.

반이중(Half-duplex)방식칩을 3개 사용하는 개념이 되겠습니다.

그냥 RS-422을 사용할수 있는 RS-422 Driver 를 2개 사용해도 되지만 시그널 4개는 필요 없으니 왠지 손해보는 느낌이고, RS-422,485 Driver 를 섞어 써도 됩니다.
기호에 맞게 회로를 구성 하면 되지만 칩을 두종류 재고로 확보하기도 애매해서 저는 그냥 RS-422 Driver 인 MAX485 을 3개 사용 하려고 합니다.



RS422과 RS485에 9핀 핀배열을 위와 같습니다.

저는 DTR신호를 추가 하려고 하니..일반적으로 많이 쓰지 않는 4번,9번에 DTR+, DTR-를 사용 할겁니다.



그리고 RS485 Driver 에서 나온 5V TTL 신호를 다시 RS232 신호인 12V 로 변환하기 위해서 RS232 Driver를 사용할겁니다.




- 작성중이므로 이후 내용은 추후에 추가 하겠습니다. -

주차장 문 개폐 리모콘키 복사하기



처가집에 가면 빌라인데 리모콘 키가 있습니다.




이렇게 생겼는데... 리모콘이 1개라서 와이프가 갈땐 저 키를 쓰고..

제 차를 타고 갈땐 그 키를 꺼내서 가지고 가야 하는데 불편해서..키를 추가로 살까 하다가...

그냥 만들어 봤습니다.

우선 주파수를 몇을 쓰는지 몰라서... 433MHz 와 315MHz 둘다 테스트 해봤는데.. 315MHz를 사용 하네요...

315mHz 방식 송/수신 모듈을 사서... 수신기로 분석한 값을 메모 해 놨다가...

송신기 만들어서 그 값을 보내주게 프로그램 했습니다...







Arduino Pro에 스위치 버튼 하나 달고.... 송신 모듈을 달아 줫습니다.

사진에 케이블을 프로그램 전송 때문에 여러 가닥인데..다 떼어 버리고...전원 5 볼트만 연결 하면 됩니다.#include <RCSwitch.h> bool bFirstRun = false; RCSwitch mySwitch = RCSwitch(); void setup() { pinMode(6, INPUT); pinMode(13, OUTPUT); Serial.begin(9600); // Transmitter is connected to Arduino Pin #10 mySwitch.enableTransmit(10); // Optional set pulse length. mySwitch.setPulseLength(447); // Optional set protocol (default is 1, will work for most outlets) //mySwitch.setProtocol(2); // Optional set number of transmission repetitions. // mySwitch.setRepeatTransmit(15); } void loop() { if (bFirstRun == false) { digitalWrite(13,HIGH); mySwitch.send(1380428, 24); //mySwitch.send(1380464, 24); //mySwitch.send(1380419, 24); bFirstRun = true; } if ( digitalRead(6) ) { digitalWrite(13,HIGH); mySwitch.send(1380428, 24); while (digitalRead(6)) { delay(1); } } delay(10); digitalWrite(13,LOW); return; /* See Example: TypeA_WithDIPSwitches */ mySwitch.switchOn("11111", "00010"); delay(1000); mySwitch.switchOff("11111", "00010"); delay(1000); /* Same switch as above, but using decimal code */ mySwitch.send(5393, 24); delay(1000); mySwitch.send(5396, 24); delay(1000); /* Same switch as above, but using binary code */ mySwitch.send("000000000001010100010001"); delay(1000); mySwitch.send("000000000001010100010100"); delay(1000); /* Same switch as above, but tri-state code */ mySwitch.sendTriState("00000FFF0F0F"); delay(1000); mySwitch.sendTriState("00000FFF0FF0"); delay(1000); delay(5000); }





원래 리모콘 수신해서 값을 분석하기 위한 수신 리시버에 코드는 다음과 같습니다.

그냥 수신만 잠시 하기 위해서 만든거니 코드 정리는 안했습니다.#include <EEPROM.h> #include <RCSwitch.h> RCSwitch mySwitch = RCSwitch(); unsigned long nEEPROMValue; void setup() { pinMode(12, OUTPUT); pinMode(13, OUTPUT); pinMode(A3, INPUT); Serial.begin(9600); Serial.println("Run"); mySwitch.enableReceive(0); // Receiver on interrupt 0 => that is pin #2 nEEPROMValue = EEPROMReadlong(1); } void loop() { if (mySwitch.available()) { output(mySwitch.getReceivedValue(), mySwitch.getReceivedBitlength(), mySwitch.getReceivedDelay(), mySwitch.getReceivedRawdata(),mySwitch.getReceivedProtocol()); Serial.println( mySwitch.getReceivedValue() ); //output(1); if (mySwitch.getReceivedValue() == nEEPROMValue) { if (digitalRead(12) == LOW) { Serial.println("on"); digitalWrite(12,HIGH); digitalWrite(13,HIGH); } else { Serial.println("off"); digitalWrite(12,LOW); digitalWrite(13,LOW); } delay(1000); } mySwitch.resetAvailable(); } if ( digitalRead(A3) == HIGH) { delay(1000); if ( digitalRead(A3) == HIGH) { digitalWrite(13,HIGH); Serial.println("TeachMode Start"); bool bLoop = true; while ( digitalRead(A3) == HIGH ) {} while (bLoop) { if ( digitalRead(A3) == HIGH) { bLoop = false; Serial.println("TeachMode End"); } if (mySwitch.available()) { nEEPROMValue = mySwitch.getReceivedValue(); EEPROMWritelong(1,nEEPROMValue); Serial.print("EEPROM Save : "); //Serial.println(EEPROMWritelong); bLoop = false; } } digitalWrite(13,LOW); } } } void EEPROMWritelong(int address, unsigned long value) { //Decomposition from a long to 4 bytes by using bitshift. //One = Most significant -> Four = Least significant byte byte four = (value & 0xFF); byte three = ((value >> 8) & 0xFF); byte two = ((value >> 16) & 0xFF); byte one = ((value >> 24) & 0xFF); //Write the 4 bytes into the eeprom memory. EEPROM.write(address, four); EEPROM.write(address + 1, three); EEPROM.write(address + 2, two); EEPROM.write(address + 3, one); } unsigned long EEPROMReadlong(long address) { //Read the 4 bytes from the eeprom memory. long four = EEPROM.read(address); long three = EEPROM.read(address + 1); long two = EEPROM.read(address + 2); long one = EEPROM.read(address + 3); //Return the recomposed long by using bitshift. return ((four << 0) & 0xFF) + ((three << 8) & 0xFFFF) + ((two << 16) & 0xFFFFFF) + ((one << 24) & 0xFFFFFFFF); }

직구한 LG TV 로컬변경 PC없이 자동으로 하기.

예전에 직구한 LG TV 로컬변경을 이전 블로그에서 포스팅 한적이 있습니다. (이전 블로그 글 링크)
지인이 이번에 또 LG TV를 직구 했는데 로컬 변경을 물어 보는데... 문제는 컴맹입니다...
그래서 컴맹도 쉽게 로컬 변경을 할수 있게 Arduino 를 사용해서 만들어 봤습니다.
서비스 단자에 이어폰 짹을 꼽고 USB 를 꼽아서 전원을 넣어주면 로컬 변경이 됩니다.
구지 사이즈가 클 필요가 없어서 Arduino Pro Mini에 Max3232 칩을 사용 했습니다.
USB 전원을 연결하면 비쥬얼 적인 효과를 위해서 LED가 깜빡이고 로컬 변경 코멘드를 전송 합니다.

그냥 단순하게 한가지 동작만 한다면 점퍼를 쓸필요가 없어서 저항 쓸 필요도 없이 아주 간단한 구성이 될텐데 괜히 범용성 생각하다가 보드가 지저분해 졌네요~
보드 뒷면인데 따로 회로 구성을 할 필요도 없이 간단 하지만 그래도 또 TV 제작 년도 별로 커멘드가 다르고, 다시 US 로컬 변경을 할 필요가 있어서 년도 선택 3개 한국,미국 선택 2개 해서..점퍼를 5개 구성해 줬습니다.
Arduino 소스 코드는 아래와 같습니다.
처음 부팅시 점퍼를 검사해서 년도모드 1~3을 검색하고 점퍼가 안 꼽혀 있으면 모드 3 입니다.
그리고 로컬 모드 KR,US를 검사해서 설정 합니다..점퍼가 안꼽혀 있으면 모드 0으로 KR로 로컬 변경을 한후 약 10초후 다시 US로 로컬 변경을 합니다. 즉 처음 보드에 전원을 넣고 KR 로 로컬 변경을 한후 보드를 빼면 KR 로컬이고... 10초 더 기다렸다가 US 로컬 변경까지 한후 보드를 빼면 US 로컬 변경이 되겠습니다.
#include <SoftwareSerial.h>

const int PinModeYear1 =  9;
const int PinModeYear2 =  8;
const int PinModeYear3 =  7;
const int PinModeKR =  2;
const int PinModeUS =  3;

String strSetName , strSetKR, strSetUS, strSetAdd;
int nModeYear = 3;
int nModeLocal = 0;

SoftwareSerial mySerial(10, 11); // RX, TX
void setup() {
  
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode (PinModeYear1, INPUT);
  pinMode (PinModeYear2, INPUT);
  pinMode (PinModeYear3, INPUT);
  pinMode (PinModeKR, INPUT);
  pinMode (PinModeUS, INPUT);

  mySerial.begin(9600);
  Serial.begin(9600);


  if (digitalRead(PinModeYear1) == HIGH) nModeYear = 1;
  if (digitalRead(PinModeYear2) == HIGH) nModeYear = 2;
  if (digitalRead(PinModeYear3) == HIGH) nModeYear = 3;
  
  if (digitalRead(PinModeKR) == HIGH) nModeLocal = 1;
  if (digitalRead(PinModeUS) == HIGH) nModeLocal = 2;

  if (nModeYear == 1) { 
    //2014년 LB5900~6000
    //2015년 55LF6000
    strSetName = "2014~2015";
    strSetKR = "AN 00 01 4B 4F 52";
    strSetUS = "AN 00 02 55 53 41";
    strSetAdd = "AF 00 81 E0";
  }
  
  if (nModeYear == 2) {
    //2015년 65UF9500 ,65UF8500 
    //한국코드 - 18077
    strSetName = "2015~";
    strSetKR = "AU 00 46 9D 01 4B 4F 52";
    strSetUS = "AU 00 57 0A 02 55 53 41";
  }
  
  if (nModeYear == 3) {
    //2016년 이후
    //한국코드 - 18048  
    strSetName = "2016~";
    strSetKR = "AU 00 46 80 01 4B 4F 52";
    strSetUS = "AU 00 57 0A 02 55 53 41";
  }

  delay(500);
  Serial.println("===========================");
  Serial.println("LG TV Local Changer   v1.0");
  Serial.println("");
  Serial.println("2017/07/27");
  Serial.println("By CodeH (haesup@gmail.com)");
  Serial.println("===========================");
  Serial.println("JP9 : Year 2014   JP2 : KR");
  Serial.println("JP8 : Year 2015   JP3 : US");
  Serial.println("JP7 : Year 2016");
  Serial.println("---------------------------");
  if (nModeYear == 1) Serial.println("2014 TV");
  if (nModeYear == 2) Serial.println("2015 TV");
  if (nModeYear == 3) Serial.println("2016 TV");
  if (nModeLocal == 0) Serial.println("Local to KR.... After 10Sec... Local to US....");
  if (nModeLocal == 1) Serial.println("Local to KR....");
  if (nModeLocal == 2) Serial.println("Local to US....");
  Serial.println("");
  delay(500);
}

void loop() {

  if (nModeLocal == 1 || nModeLocal == 0) {
    digitalWrite(LED_BUILTIN, HIGH);
    delay(1000);
    digitalWrite(LED_BUILTIN, LOW);    
    delay(2000);
    Blink_CountDown(30);
    Serial.print("Set Local to Kor : ");
    Serial.println(strSetName);  
    Serial.print("Command : ");
    Serial.println(strSetKR);  
    mySerial.println(strSetKR);
    delay(2000);
    digitalWrite(LED_BUILTIN, HIGH);
    delay(1000);
    digitalWrite(LED_BUILTIN, LOW);   
    delay(500); 
    
    delay(5000);
  }
  
  
  
  if (nModeLocal == 2 || nModeLocal == 0) {
    digitalWrite(LED_BUILTIN, HIGH);
    delay(1000);
    digitalWrite(LED_BUILTIN, LOW);    
    delay(500);
    digitalWrite(LED_BUILTIN, HIGH);
    delay(1000);
    digitalWrite(LED_BUILTIN, LOW);    
    delay(2000);
    Blink_CountDown(40);
    Serial.print("Set Local to US : ");
    Serial.println(strSetName);  
    Serial.print("Command : ");
    Serial.println(strSetUS);  
    mySerial.println(strSetUS);
    delay(2000);
    digitalWrite(LED_BUILTIN, HIGH);
    delay(1000);
    digitalWrite(LED_BUILTIN, LOW);    
    delay(500);
    digitalWrite(LED_BUILTIN, HIGH);
    delay(1000);
    digitalWrite(LED_BUILTIN, LOW);    
    delay(500);
    
    delay(5000);
  }
  
  Serial.println("Work Finish!!!!!");
  while (1) delay (100);
}

void Blink_CountDown(int in) 
{
  int i;  
  for (int j = in ; j >= 0 ; --j) {
    i = j;
    if (i < 5) i = 5;
    if (i > 30) i = 30;
    digitalWrite(LED_BUILTIN, HIGH);
    delay(i * 10);
    digitalWrite(LED_BUILTIN, LOW);
    delay(i * 10);    
    Serial.print(".");
  }
  Serial.println("");
}
PC에 연결해서 점퍼 연결에 따라 커맨드가 정상적으로 전송 되는것을 확인 했고 이제 TV에 바로 연결 할수 있도록 이어폰 짹으로 변경 했습니다.
서비스 단자에 RX,TX가 항상 헷갈려서.... RX,TX 바꺼서 꼽을수 있게 짹 타입으로 하다보니 좀 지저분 하네요....확인해 보고 잘되는 핀 찾아서 그냥 납땜해 버려야 겠습니다.
서비스 단자에 4.5파이 이어폰 케이블 꼽고 USB 전원 넣고... 끝...
LED가 비쥬얼 적인 효과로 깜빡이긴 하는게...좀 기다려야 하네요...
그거 시름 그냥 딜레이 빼면 5초안에 가능 하겠군요~
[video width="720" height="404" mp4="http://codeh.kr/wp-content/uploads/2017/07/KakaoTalk_Video_20170728_1529_19_013.mp4"][/video]
설정 - 일반에서 국가 선택에 미국 밖에 없는데...
로컬 변경을 하면...이렇게 한국을 선택 할수 있습니다.
채널 검색에서도 한국 방송 잘~ 잡힙니다~
사실 서비스포트 프로토콜만 안다면...
따로 점퍼 스위치 안쓰고.... 보드에서 TV로 쿼리 날리고 답변온 티비 모델명을 가지고
거기에 맞는 커멘드를 날려주면 완전 자동으로 가능 하겠지만...자료를 구할데가 없으니 그냥 단방향으로 커멘드만 날리는 것만 가능 하겠군요..

그리고 새로운 커맨드가 있다면 커맨드 공유 해 주시면 소스 코드에 반영 하겠습니다~