├── LICENSE.txt ├── README.md ├── docs ├── demo.jpg ├── remote1.jpg ├── remote2.jpg ├── remote3.jpg ├── remote4.jpg ├── saleae │ ├── 11-22-33_8_MHz_24_M_Samples.logicdata │ ├── 12-34-56_8_MHz_24_M_Samples.logicdata │ ├── remote_8_MHz_24_M_Samples.logicdata │ ├── saleae-11-22-33.jpg │ ├── saleae-12-34-56.jpg │ ├── saleae-remote.jpg │ ├── saleae-transmit.jpg │ └── transmit_8_MHz_24_M_Samples.logicdata └── schematics.pdf └── remotes.md /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Mike Causer 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MicroPython YS-IRTM 2 | 3 | MicroPython examples for YS-IRTM 5V NEC Infrared UART transceivers. 4 | 5 | ![demo](docs/demo.jpg) 6 | 7 | Features dual 38KHz 940nm IR TX/RX LEDs and a micro controller which provides a UART interface. 8 | 9 | This is a 5V logic device, so if you wish to use with a 3V3 MCU such as the ESP32, you'll need a level shifter or voltage divider. 10 | 11 | ## Examples 12 | 13 | TinyPICO ESP32 > Level shifter > YS-IRTM 14 | 15 | ```python 16 | import time 17 | from machine import Pin, UART 18 | uart = UART(1, tx=14, rx=15, baudrate=9600) 19 | 20 | # sniff for a remote 21 | def sniff(): 22 | while True: 23 | if uart.any(): 24 | print(uart.readline()) 25 | 26 | # eg. received b'\x00\xff\x45' 27 | 28 | # replay a remote 29 | def replay(): 30 | uart.write(bytearray(b'\xa1\xf1\x00\xff\x45')) 31 | uart.read() 32 | # read returns b'\xf1' to say command confirmed 33 | 34 | # send a 5 byte packet, return bool if confirmed sent 35 | def tx(buf, timeout_ms=1000): 36 | uart.write(buf) 37 | timeout = time.ticks_ms() + timeout_ms 38 | while time.ticks_ms() < timeout: 39 | if uart.any(): 40 | resp = uart.read() 41 | if len(resp) > 0: 42 | return buf[1] == resp[0] 43 | time.sleep_ms(20) 44 | print(buf, 'timeout') 45 | return False 46 | 47 | # send a variable length string by splitting into chunks of 3 data bytes 48 | def send_string(value): 49 | buf = bytearray(b'\xa1\xf1\x00\x00\x00') 50 | # pad string to length divisible by 3 51 | if len(value) % 3: 52 | value += ' ' * (3 - len(value) % 3) 53 | for i in range(0,len(value),3): 54 | buf[2:] = bytes(value[i:i+3],'utf-8') 55 | while not tx(buf): 56 | print(buf, 'resend') 57 | 58 | # receive a variable length string 59 | # waits for a gap in received packets before printing 60 | def receive_string(): 61 | while True: 62 | last_size = uart.any() 63 | if last_size > 0: 64 | time.sleep_ms(400) # around 270ms each tx 65 | size = uart.any() 66 | if last_size == size: 67 | print(uart.read()) 68 | print(time.ticks_diff(time.ticks_ms(), start)) 69 | else: 70 | last_size = size 71 | else: 72 | time.sleep_ms(20) 73 | start = time.ticks_ms() 74 | 75 | # on device 1 76 | receive_string() 77 | 78 | # on device 2 79 | send_string('this is not the most efficient way to send lots of text but it works!') 80 | send_string('abcdefghijklmnopqrstuvwxyz') 81 | 82 | # on device 1 83 | # b'this is not the most efficient way to send lots of text but it works!' 84 | # 6402 85 | # b'abcdefghijklmnopqrstuvwxyz ' 86 | # 2801 87 | 88 | # define something to print when a matching code is detected 89 | cb = {0: {255: {0x45: '1', 0x46: '2', 0x47: '3'}}} 90 | 91 | # press a buttons 1, 2 and 3 on a remote 92 | # button 1 = b'\x00\xFF\x45' 93 | # button 2 = b'\x00\xFF\x46' 94 | # button 3 = b'\x00\xFF\x47' 95 | def print_button(): 96 | while True: 97 | try: 98 | if uart.any(): 99 | buf = uart.read() 100 | if len(buf) == 3: 101 | print(cb[buf[0]][buf[1]][buf[2]]) 102 | else: 103 | print(buf, 'unexpected length') 104 | time.sleep_ms(20) 105 | except KeyError: 106 | print(buf, 'unexpected key') 107 | # prints 1, 2, 3 108 | ``` 109 | 110 | I have a few remotes which work with this IR receiver, see [remotes](remotes.md) for which codes each button sends. 111 | 112 | ## Pinout 113 | 114 | Pin | Name | Description 115 | :--:|:----:|:-------------------------------- 116 | 1 | GND | Ground 117 | 2 | RXD | UART receive 118 | 3 | TXD | UART transmit 119 | 4 | VCC | Supply voltage 5V 120 | 121 | ## Transmit Protocol 122 | 123 | Payload consists of 5 bytes and if accepted, the device will reply with the command byte. 124 | 125 | If the payload is not understood, the device will not respond. Only the command byte is used as confirmation. 126 | 127 | Payload = (Address, Command, Data 1, Data 2, Data 3), eg. 128 | 129 | ```python 130 | >>> uart.write(bytearray(b'\xa1\xf1\x01\x02\x03')) 131 | >>> print(uart.read()) 132 | b'\xf1' 133 | ``` 134 | 135 | The first two bytes (Address + Command) are for instructing the modules microcontroller. The next 3 data bytes are what's actually transmitted. 136 | 137 | When you send data `0x00 0xFF 0x45`, what's actually being IR blasted is `0x00 0xFF 0x45 0xBA`. The 4th data byte is automatically appended. 138 | 139 | `Leading burst (low), Space (high), Inverse Address (0x00), Address (0xFF), Command (0x45), Inverse Command (0xBA)` 140 | 141 | The 4th byte Inverse Command is calculated automatically from the 3rd data byte Command. 142 | 143 | Command `0x45` = `0b01000101`, each bit inverted is `0b10111010` = `0xBA` Inverse Command. 144 | 145 | There is no validation around the two address bytes (Inverse Address + Address). 146 | The 1st data byte does not have to be the inverse of the 2nd data byte. 147 | 148 | If you send `0x11 0x22 0x33`, it's sending `0x11 0x22 0x33 0xCC`. The `0x11` is _supposed to be_ the inverse of `0x22`. 149 | It still sends though. I assume this is to make the module more flexible with different IR protocols. 150 | 151 | ### Device Address 152 | 153 | The device has a feature where you can give the module an address (0-255) and it will ignore UART lines that do not begin with the address. 154 | 155 | The default address is `A1` and is changeable with the `F2` command. 156 | If you change the device address, eg to `A2`, then try to send to `A1`, the payload will be ignored. 157 | Resend to `A2` and the payload will be accepted and actioned. 158 | 159 | If you change the address, but forget what it is, fear not. There is a failsafe address `FA`. 160 | If you have changed your device address and it's not responding, you can use address `FA` to reset it. 161 | Or just always send to `FA` and ignore the address feature completely. 162 | 163 | ### Command, Data 1, Data 2 and Data 3 164 | 165 | `F1` command to transmit. The 3 data bytes are NEC user code high, user code low, command code. 166 | 167 | `F2` command to change address. Data 1 is the new address. Use zeros for Data 2 and 3. 168 | 169 | `F3` command to change serial baud rate. Data 1 is the new baud rate (1-4). Use zeros for Data 2 and 3. 170 | 171 | Baud rates: `1` = 4800bps, `2` = 9600bps, `3` = 19200bps, `4` = 57600bps. 172 | 173 | ## Receive Protocol 174 | 175 | When the recipient device detects a signal, it will send the 3 data bytes over UART. 176 | 177 | Two address bytes and a command byte. The inverse command byte is not sent over UART. 178 | 179 | You can receive from a remote that uses the NEC protocol, or from a second YS-IRTM module. 180 | 181 | NEC repeat codes are not supported. Holding down a button on a remote does nothing and you only get a single capture. 182 | 183 | **Sender YS-IRTM:** 184 | 185 | ```python 186 | >>> uart.write(bytearray(b'\xa1\xf1\x01\x02\x03')) 187 | >>> print(uart.read()) 188 | b'\xf1' 189 | ``` 190 | 191 | **Receiver YS-IRTM:** 192 | 193 | ```python 194 | >>> print(uart.read()) 195 | b'\x01\x02\x03' 196 | ``` 197 | 198 | ## Examples 199 | 200 | Address | Command | Data 1 | Data 2 | Data 3 | Description | Response 201 | ------- | ------- | ------ | ------ | ------ | ---------------------------------------- | -------- 202 | A1 | F1 | 01 | 02 | 03 | transmit 01 02 03 | F1 203 | A1 | F1 | AA | BB | CC | transmit AA BB CC | F1 204 | FA | F1 | BB | CC | DD | transmit BB CC DD using failsafe addr | F1 205 | AB | F1 | 01 | 02 | 03 | unknown addr AB, packet ignored | - 206 | A1 | F2 | A2 | 00 | 00 | change addr from A1 to A2 | F2 207 | A1 | F2 | A3 | 00 | 00 | unknown addr A1, packet ignored | - 208 | FA | F2 | A1 | 00 | 00 | change addr from A2 to A1 using failsafe | - 209 | A1 | F3 | 01 | 00 | 00 | set baud rate 4800bps | F3 210 | A1 | F3 | 02 | 00 | 00 | set baud rate 9600bps | F3 211 | A1 | F3 | 03 | 00 | 00 | set baud rate 19200bps | F3 212 | A1 | F3 | 04 | 00 | 00 | set baud rate 57600bps | F3 213 | 214 | ## Saleae Logic Analyser Capture 215 | 216 | Connected a [TL1838 IR receiver module](https://www.aliexpress.com/item/32967589687.html) to a [Saleae logic analyser](https://www.saleae.com/), powered by 5V and captured the signal pin. 217 | 218 | ### Capture 1 219 | 220 | Black remote with blue d-pad at bottom - button 1. 221 | 222 | Received `0x00 0xFF 0x45` over UART. 223 | 224 | Received `0x00 0xFF 0x45 0xBA` over IR. 225 | 226 | [capture 1](docs/saleae/remote_8_MHz_24_M_Samples.logicdata) 227 | 228 | ![capture 1](docs/saleae/saleae-remote.jpg) 229 | 230 | ### Capture 2 231 | 232 | Replay remote button 1 with YS-IRTM. 233 | 234 | Sent `0x00 0xFF 0x45` over UART. 235 | 236 | Sent `0x00 0xFF 0x45 0xBA` over IR. 237 | 238 | [capture 2](docs/saleae/transmit_8_MHz_24_M_Samples.logicdata) 239 | 240 | ![capture 2](docs/saleae/saleae-transmit.jpg) 241 | 242 | ### Capture 3 243 | 244 | Sent `0x11 0x22 0x33` over UART. 245 | 246 | Sent `0x11 0x22 0x33 0xCC` over IR. 247 | 248 | [capture 3](docs/saleae/11-22-33_8_MHz_24_M_Samples.logicdata) 249 | 250 | ![capture 3](docs/saleae/saleae-11-22-33.jpg) 251 | 252 | ### Capture 4 253 | 254 | Sent `0x12 0x34 0x56` over UART. 255 | 256 | Sent `0x12 0x34 0x56 0xA9` over IR. 257 | 258 | [capture 4](docs/saleae/12-34-56_8_MHz_24_M_Samples.logicdata) 259 | 260 | ![capture 4](docs/saleae/saleae-12-34-56.jpg) 261 | 262 | ## Parts 263 | 264 | * [YS-IRTM](https://www.aliexpress.com/item/32647529087.html) $2.09 AUD 265 | * [TinyPICO](https://www.tinypico.com/) $20.00 USD 266 | * [Logic level converter](https://www.aliexpress.com/item/32589088559.html) $0.45 AUD 267 | * [TL1838 IR receiver module](https://www.aliexpress.com/item/32967589687.html) $0.27 AUD 268 | * [Saleae Logic 8](https://www.saleae.com) $639 AUD 269 | 270 | ## Links 271 | 272 | * [micropython.org](http://micropython.org) 273 | * [Schematics](docs/schematics.pdf) 274 | * [TinyPICO Getting Started](https://www.tinypico.com/gettingstarted) 275 | 276 | ## License 277 | 278 | Licensed under the [MIT License](http://opensource.org/licenses/MIT). 279 | 280 | Copyright (c) 2019 Mike Causer 281 | -------------------------------------------------------------------------------- /docs/demo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcauser/micropython-ys-irtm/95fee0cdd1c91a07227857a36ce9baa9858973b5/docs/demo.jpg -------------------------------------------------------------------------------- /docs/remote1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcauser/micropython-ys-irtm/95fee0cdd1c91a07227857a36ce9baa9858973b5/docs/remote1.jpg -------------------------------------------------------------------------------- /docs/remote2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcauser/micropython-ys-irtm/95fee0cdd1c91a07227857a36ce9baa9858973b5/docs/remote2.jpg -------------------------------------------------------------------------------- /docs/remote3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcauser/micropython-ys-irtm/95fee0cdd1c91a07227857a36ce9baa9858973b5/docs/remote3.jpg -------------------------------------------------------------------------------- /docs/remote4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcauser/micropython-ys-irtm/95fee0cdd1c91a07227857a36ce9baa9858973b5/docs/remote4.jpg -------------------------------------------------------------------------------- /docs/saleae/11-22-33_8_MHz_24_M_Samples.logicdata: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcauser/micropython-ys-irtm/95fee0cdd1c91a07227857a36ce9baa9858973b5/docs/saleae/11-22-33_8_MHz_24_M_Samples.logicdata -------------------------------------------------------------------------------- /docs/saleae/12-34-56_8_MHz_24_M_Samples.logicdata: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcauser/micropython-ys-irtm/95fee0cdd1c91a07227857a36ce9baa9858973b5/docs/saleae/12-34-56_8_MHz_24_M_Samples.logicdata -------------------------------------------------------------------------------- /docs/saleae/remote_8_MHz_24_M_Samples.logicdata: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcauser/micropython-ys-irtm/95fee0cdd1c91a07227857a36ce9baa9858973b5/docs/saleae/remote_8_MHz_24_M_Samples.logicdata -------------------------------------------------------------------------------- /docs/saleae/saleae-11-22-33.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcauser/micropython-ys-irtm/95fee0cdd1c91a07227857a36ce9baa9858973b5/docs/saleae/saleae-11-22-33.jpg -------------------------------------------------------------------------------- /docs/saleae/saleae-12-34-56.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcauser/micropython-ys-irtm/95fee0cdd1c91a07227857a36ce9baa9858973b5/docs/saleae/saleae-12-34-56.jpg -------------------------------------------------------------------------------- /docs/saleae/saleae-remote.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcauser/micropython-ys-irtm/95fee0cdd1c91a07227857a36ce9baa9858973b5/docs/saleae/saleae-remote.jpg -------------------------------------------------------------------------------- /docs/saleae/saleae-transmit.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcauser/micropython-ys-irtm/95fee0cdd1c91a07227857a36ce9baa9858973b5/docs/saleae/saleae-transmit.jpg -------------------------------------------------------------------------------- /docs/saleae/transmit_8_MHz_24_M_Samples.logicdata: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcauser/micropython-ys-irtm/95fee0cdd1c91a07227857a36ce9baa9858973b5/docs/saleae/transmit_8_MHz_24_M_Samples.logicdata -------------------------------------------------------------------------------- /docs/schematics.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcauser/micropython-ys-irtm/95fee0cdd1c91a07227857a36ce9baa9858973b5/docs/schematics.pdf -------------------------------------------------------------------------------- /remotes.md: -------------------------------------------------------------------------------- 1 | # Remotes 2 | 3 | A few of my remotes which I've captured. 4 | 5 | #### Black remote with blue d-pad at bottom 6 | 7 | ![remote1](docs/remote1.jpg) 8 | 9 | [Buy on AliExpress](https://www.aliexpress.com/item/32307163446.html) 10 | 11 | Addr High | Addr Low | Command | Button 12 | --------- | -------- | ------- | ------ 13 | 00 | FF | 45 | 1 14 | 00 | FF | 46 | 2 15 | 00 | FF | 47 | 3 16 | 00 | FF | 44 | 4 17 | 00 | FF | 40 | 5 18 | 00 | FF | 43 | 6 19 | 00 | FF | 07 | 7 20 | 00 | FF | 15 | 8 21 | 00 | FF | 09 | 9 22 | 00 | FF | 16 | star 23 | 00 | FF | 19 | 0 24 | 00 | FF | 0D | hash 25 | 00 | FF | 18 | up 26 | 00 | FF | 08 | left 27 | 00 | FF | 1C | ok 28 | 00 | FF | 5A | right 29 | 00 | FF | 52 | down 30 | 31 | 32 | #### White remote with red power button 33 | 34 | ![remote2](docs/remote2.jpg) 35 | 36 | [Buy on AliExpress](https://www.aliexpress.com/item/32764250708.html) 37 | 38 | Addr High | Addr Low | Command | Button 39 | --------- | -------- | ------- | ------ 40 | 00 | FF | 45 | power 41 | 00 | FF | 47 | menu 42 | 00 | FF | 44 | test 43 | 00 | FF | 40 | plus 44 | 00 | FF | 43 | back 45 | 00 | FF | 07 | prev 46 | 00 | FF | 15 | play 47 | 00 | FF | 09 | next 48 | 00 | FF | 16 | 0 49 | 00 | FF | 19 | minus 50 | 00 | FF | 0D | c 51 | 00 | FF | 0C | 1 52 | 00 | FF | 18 | 2 53 | 00 | FF | 5E | 3 54 | 00 | FF | 08 | 4 55 | 00 | FF | 1C | 5 56 | 00 | FF | 5A | 6 57 | 00 | FF | 42 | 7 58 | 00 | FF | 52 | 8 59 | 00 | FF | 4A | 9 60 | 61 | 62 | #### TV tuner silver remote with red power and green mute 63 | 64 | ![remote3](docs/remote3.jpg) 65 | 66 | [Buy on AliExpress](https://www.aliexpress.com/item/4000068546117.html) 67 | 68 | Addr High | Addr Low | Command | Button 69 | --------- | -------- | ------- | ------ 70 | 00 | FF | 4D | power 71 | 00 | FF | 54 | source 72 | 00 | FF | 16 | mute 73 | 00 | FF | 4C | record 74 | 00 | FF | 05 | ch+ 75 | 00 | FF | 0C | time shift 76 | 00 | FF | 0A | vol- 77 | 00 | FF | 40 | full screen 78 | 00 | FF | 1E | vol+ 79 | 00 | FF | 12 | 0 80 | 00 | FF | 02 | ch- 81 | 00 | FF | 1C | recall 82 | 00 | FF | 09 | 1 83 | 00 | FF | 1D | 2 84 | 00 | FF | 1F | 3 85 | 00 | FF | 0D | 4 86 | 00 | FF | 19 | 5 87 | 00 | FF | 1B | 6 88 | 00 | FF | 11 | 7 89 | 00 | FF | 15 | 8 90 | 00 | FF | 17 | 9 91 | 92 | 93 | #### 44 key RGB LED remote 94 | 95 | ![remote4](docs/remote4.jpg) 96 | 97 | [Buy on AliExpress](https://www.aliexpress.com/item/32958464220.html) 98 | 99 | Addr High | Addr Low | Command | Button 100 | --------- | -------- | ------- | ------ 101 | 00 | FF | 5C | bright up 102 | 00 | FF | 5D | bright down 103 | 00 | FF | 41 | next 104 | 00 | FF | 40 | power 105 | 00 | FF | 58 | R 106 | 00 | FF | 59 | G 107 | 00 | FF | 45 | B 108 | 00 | FF | 44 | W 109 | 00 | FF | 54 | r1 110 | 00 | FF | 55 | g1 111 | 00 | FF | 49 | b1 112 | 00 | FF | 48 | w1 113 | 00 | FF | 50 | r2 114 | 00 | FF | 51 | g2 115 | 00 | FF | 4D | b2 116 | 00 | FF | 4C | w2 117 | 00 | FF | 1C | r3 118 | 00 | FF | 1D | g3 119 | 00 | FF | 1E | b3 120 | 00 | FF | 1F | w3 121 | 00 | FF | 18 | r4 122 | 00 | FF | 19 | g4 123 | 00 | FF | 1A | b4 124 | 00 | FF | 1B | w4 125 | 00 | FF | 14 | red up 126 | 00 | FF | 15 | green up 127 | 00 | FF | 16 | blue up 128 | 00 | FF | 17 | quick 129 | 00 | FF | 10 | red down 130 | 00 | FF | 11 | green down 131 | 00 | FF | 12 | blue down 132 | 00 | FF | 13 | slow 133 | 00 | FF | 0C | diy 1 134 | 00 | FF | 0D | diy 2 135 | 00 | FF | 0E | diy 3 136 | 00 | FF | 0F | auto 137 | 00 | FF | 08 | diy 4 138 | 00 | FF | 09 | diy 5 139 | 00 | FF | 0A | diy 6 140 | 00 | FF | 0B | flash 141 | 00 | FF | 04 | jump 3 142 | 00 | FF | 05 | jump 7 143 | 00 | FF | 06 | fade 3 144 | 00 | FF | 07 | fade 7 145 | --------------------------------------------------------------------------------