Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.
|
Forum Index : Microcontroller and PC projects : Csub NECSend for the PicoMite
Author | Message | ||||
morgs67 Regular Member Joined: 10/07/2019 Location: AustraliaPosts: 75 |
I am working on a universal remote control that can automate tasks such as turning on the TV, amplifier and program source, with the required settings on each. All the items work with the NEC IR protocol. I have been using a MicroMite with the NECSend Csub to prove the concept. I would like to use a PicoMite, but so far have had no success in finding or building a Csub. Can any of you gurus help please? Thanks Tony |
||||
TassyJim Guru Joined: 07/08/2011 Location: AustraliaPosts: 6098 |
DEVICE BITSTREAM pinno, n_transitions, array%() should do the job. One array for each character. Jim VK7JH MMedit MMBasic Help |
||||
phil99 Guru Joined: 11/02/2018 Location: AustraliaPosts: 2135 |
If there aren't too many codes you can record them with an IR receiver and CSub LOG (not tested on latest firmware). Then use it's output combined with pulses for the 38kHz carrier (13µS high and 13µS low) to construct arrays for DEVICE BITSTREAM. The saved arrays can then drive the IR LED via a transistor. A short MMBasic program could automate the conversion process. The output array of CSub LOG is in the form of +timestamps for rising edges and -timestamps for falling edges. Latest version of LOG Edited 2024-01-22 15:28 by phil99 Footnote added 2024-01-22 16:31 by phil99 Attempted to use CSub LOG on latest firmware but no-go. Footnote added 2024-01-23 21:36 by phil99 CSub Log has been recompiled for V5.08.00 by @disco4now and is now working. |
||||
morgs67 Regular Member Joined: 10/07/2019 Location: AustraliaPosts: 75 |
I was hoping Matherp could produce a version of his NECSend pin_number, device, code for the PicoMite. I am using that on the MicroMite (as well as the decoder). When I tried to produce the Csub it would not assemble and not knowing enough I came to a halt. Tony |
||||
phil99 Guru Joined: 11/02/2018 Location: AustraliaPosts: 2135 |
Here is a NECsend Sub that works with all the devices I have that use the NEC protocol. Boith 16 bit and 8 bit address devices work. The main difference with the CSub is it uses 2 pins for the output, one for data and the other for 38kHz modulation. The driver transistor combines them. Diagnostic Print statements can be removed. The demo program is a simple repeater with a 2 second delay to distinguish the original and repeated signals. ' NEC IR Remote Control repeater. Dim integer dev, key 'codes for Device (address) and Button (data) Const IRpin = MM.Info(pinno gp1) 'output pins, change as needed Const kHz38 = MM.Info(pinno gp3) 'also change PWM channel to match (3 places) SetPin IRpin, dout : Pin(IRpin) = 0 ' IR code output SetPin kHz38, pwm ' IR carrier frequency PWM 1,38000,,5 SetPin gp6,ir ' IR receiver input, change as needed IR dev, key , int Sub int ' get IR codes Print dev,Bin$(dev,8), key,Bin$(key,8) Pause 2000 NECsend IRpin,dev,key ' call transmitter sub End Sub Do : Loop End Sub NECsend IRpin As integer, dev As integer, key As integer Print dev,Bin$(dev,8), key,Bin$(key,8) Local integer word, c(73), i word = (dev<<16) + (key<<8) + ((255 Xor key )And 255) 'assemble 32 bits Pin(IRpin) = 0 PWM 1,38000,,50 Print "Data to convert " Bin$(word,32) Math set 1, c() c(0)=16 : c(1)=8 ' start pulse time units - 1 unit = 562µS For i = 2 To 66 Step 2 c(i)= ((word>>(32-i/2)) And 1)*2 + 1 'decode 32 bit word to bit time units Next c(66)=1 'end pulse time units c(67)=72 : c(68)=16 :c(69)=4 :c(70)=1 :c(71)=172 Math scale c(), 562, c() 'restore time values to uS Math V_PRINT c() 'print the bitstream Device bitstream IRpin, 67, c() 'send the data Pause 100 Pin(IRpin) = 0 PWM 1,38000,,0.1 End Sub Edited 2024-02-11 07:01 by phil99 |
||||
phil99 Guru Joined: 11/02/2018 Location: AustraliaPosts: 2135 |
And now a 1 output pin version of the program above. 38kHz carrier added to the Bitstream. Same circuit as above minus the 1N914. ' NEC IR Remote Control repeater. - 1 pin version Dim integer dev, key 'codes for Device (address) and Button (data) Const IRpin = MM.Info(pinno gp1) 'output pin, change as needed SetPin IRpin, dout : Pin(IRpin) = 0 ' IR code output SetPin gp6, IR ' IR receiver input, change as needed IR dev, key , Rx.int Print "Waiting for input" Sub Rx.int ' get IR codes Print "dev"; dev,Bin$(dev,8), "key";key,Bin$(key,8);" Recieved code" Pause 2000 'delay to separate original and repeated code NECsend IRpin,dev,key ' call transmitter sub Print "Waiting for input" End Sub Do : Loop End Sub NECsend IRpin As integer, dev As integer, key As integer Print "dev";dev,Bin$(dev,8), "key";key,Bin$(key,8);" Data to send" Local integer word, c(72), i, d(2200), n word = (dev<<16) + (key<<8) + ((255 Xor key )And 255) 'assemble 32 bits Pin(IRpin) = 0 Print "Data to convert " Bin$(word,32) Math set 1, c() c(0)=16 : c(1)=8 ' start pulse time units - 1 unit = 562S For i = 2 To 68 Step 2 c(i)= ((word>>(32-i/2)) And 1)*2 + 1 'decode 32 bit word to bit time units Next c(66)=1 'end pulse time units c(67)=72 : c(68)=16 :c(69)=4 :c(70)=1 :c(71)=172 Math scale c(), 562, c() 'restore time values to uS ' Math V_PRINT c() 'print the bitstream Math set 13 , d() 'Load d() with PWM, 13=1000/(38*2)uS = half cycle @ 38kHz unit = 42 'half cycles - basic time unit D(unit * 16) = 562 * 8 'pause after start pulse train n = 2 For m=(unit * (16 + 1)) To 2100 Step unit 'load data after start sequence d(m) = c(n) 'copy data duration (short = 0, long = 1) Inc n, 2 'skip to next data bit Print n,m, c(n), d(m) Next Device bitstream IRpin, 2199, d() 'send the data Pause 100 Pin(IRpin) = 0 End Sub Edited 2024-02-12 15:28 by phil99 |
||||
morgs67 Regular Member Joined: 10/07/2019 Location: AustraliaPosts: 75 |
This link provides an overview of the NEC IR protocol in the first few pages- https://www.ad-notam.com/attachment/742/download/td_dfu_ir-protocol_v4-0_nec-format_20140618.pdf The most important part is the four bytes of data are sent with the bits in each byte sent with the least significant bit first. As an example I have been matching the output of phil99's PicoMite decoder to the MicroMite NECSend Csub. For example to control the Bush internet radio by MicroMite use NECSend IRTx,18,6 to have Device 18 go to KeyCode 6 (preset 6). The Pico repeater/decoder output is: DevCode 18615 100100010110111 KeyCode 96 01100000 Received code DevCode 18615 100100010110111 KeyCode 96 01100000 Data to send Data to convert 01001000 10110111 01100000 10011111 DevCode invDevCode Command invCommand Now Reorder bits 00010010 00000110 Equals Device code 18 Command 6 The same as the MicroMite NEC code For a device using the Extended protocol- An Onkyo Amp volume down is NECSend IRTx,28114,3 The Pico repeater/decoder output is: DevCode 19382 100101110110110 KeyCode 192 11000000 Received code DevCode 19382 100101110110110 KeyCode 192 11000000 Data to send Data to convert 01001011 10110110 11000000 00111111 Address low Add high command invCommand Now Reorder bits 0110 1101 1101 0010 00000011 (address high and low are reordered as one) 6 D D 2 HEX 3 Equals Device code 6DD2 =28114 Command 3 The same as the MicroMite NEC code Edited 2024-02-21 17:17 by morgs67 |
||||
phil99 Guru Joined: 11/02/2018 Location: AustraliaPosts: 2135 |
Cleaned the sub up a bit and removed debug prints. Const IRpin = MM.Info(pinno gp1) 'output pin, change as needed SetPin IRpin, dout : Pin(IRpin) = 0 ' IR code output Do 'Your program here. Input "Enter Device and Key codes "; dev, key NECsend IRpin, dev, key Loop Sub NECsend IRpin As integer, dev As integer, key As integer Local integer word, d(2200), m, n = 1 word = (dev<<16) + (key<<8) + ((255 Xor key )And 255) 'assemble 32 bits Math set 13 , d() '13=1000/(38*2)uS duration of a half cycle @ 38kHz d(672) = 4500 'pause after start pulse train For m = 714 To 2100 Step 42 'load data after start sequence d(m) = (((word>>(32-n)) And 1)*2 + 1) * 562.5 'convert bits to duration (short = 0, long = 1) Inc n 'step to next data bit Next Device bitstream IRpin, 2199, d() 'send the data Pause 100 Pin(IRpin) = 0 End Sub Edit. Trimmed it down a bit further. End sequence removed, which flags a long button press. This seemed to be needed for the Power button on one device (to guard against an accidental press, I guess). If it's a problem let me know and I will put it back in. Edited 2024-02-22 12:41 by phil99 |
||||
morgs67 Regular Member Joined: 10/07/2019 Location: AustraliaPosts: 75 |
Hi phill99, I have had trouble getting this to work with an Onkyo receiver. The earlier NECSub on a micromite worked perfectly to control all functions. Using a digital CRO There was a long pulse just after the start of the final bit of the output IR pulses. The final bit was a logical 1 and the long pulse occured before the completion of the total time. This was not present on the micromite output. After some experimenting I found that changing c(66)=1 to C(66)=8 moved the long pulse later and the Onkyo could be controlled. Your later version "Cleaned the sub up a bit and removed debug prints." shows the same long pulse at at the end, and is not recognised by the Onkyo. Is there a way to adjust this version? Tony |
||||
phil99 Guru Joined: 11/02/2018 Location: AustraliaPosts: 2135 |
None of the devices I have seem to care what is after the final pulse, except one that uses the "repeat" sequence after the code for the power button. What you could try is reducing the number of transitions being sent. The current value is longer than necessary, but doesn't affect anything I have. Device bitstream IRpin, 2199, d() 'send the data The value 2199 can be reduced to a minimum of 2058.My devices stop responding below that, so experiment with values no lower than that in multiples of 42. Eg next is 2100 then 2142. Let me know what works for you and I will make that the standard. Edited 2024-03-04 22:23 by phil99 Footnote added 2024-03-17 20:42 by phil99 17/03 Assuming no news is good news, here is the updated NECsend attached to the end of this program. ' IR Remote Control key recorder and translator And this the sort of data it appends to the programSub MM.STARTUP :Run :End Sub Const Fname$ = "IR Code Translator 01.bas" Option base 0 Const IRin = MM.Info(pinno gp1) 'input from IR receiver Const IRout = MM.Info(pinno gp0) 'outout to IR LED SetPin IRout, Dout : Pin(IRout) = 0 SetPin IRin, IR Dim integer K(255), Key.data=0, R.new=0, R.old=0, Set.def.key=0 'Key.data = flag to record codes (0) or send codes (1) On Error skip Settings 'replace defaults with recorded values if Sub Settings exists Dim integer dev.out = R.old, new.IRremote = R.new Dim integer dev.in, key.in, new.key, new.dev, x=0, ready = 1 Math set Set.def.key, K() 'set undefined keys to "Info" or other harmless key CLS 255 On error skip K.data 'Add key data from Sub K.data to K() - over-writing Math Set values for defined keys Print "settings - Key data recorded"; Key.data,"new device"; R.new,"old device"; R.old,"default key"; Set.def.key If Key.data Then ' if key data exists use it, else record it Print "Sending translated Codes" Text MM.HRes/2,MM.VRes*.5, " Ready ","CM",,2 Else Print "Recording Codes to:- ";Fname$ Print "press a new remote key then same key on old remote" Print "The first pair will be used as the default for any un-allocated keys." Print " Use 'Info.' or other harmless key" Print "repeat for all keys." Print "Tap any console key when finished" If Right$(Date$,3)="000" Then Dim DT$ Line Input "Type the date ",DT$ Date$=DT$ Line Input "Type the time ",DT$ Time$=DT$ EndIf Print " 'Recording keys at "+DateTime$(NOW) On KEY Finished 'Tap a keyboard key to finish recording. Sub Finished completes the file & restarts. Save Fname$ 'copy program to A: Pause 500 Open Fname$ For append As #3 'prepare to add data to the program Pause 30 EndIf IR dev.in, key.in, IRint 'receive IR codes Sub IRint 'respond to IR input If ready Then ready = 0 'only accept a code if processing of previous one is finished new.dev = dev.in : new.key = key.in 'save codes to prevent changes during processing If Key.data Then If new.dev=R.new Then 'if new remote recorded code exist translate it and send it NECsend IRout, R.old, K(new.key) Text MM.HRes/2,MM.VRes*.3, " key in "+Str$(new.dev)+" "+Str$(new.key)+" ","CM",,2 Text MM.HRes/2,MM.VRes*.5, " Translated to:- ","CM",,2 Text MM.HRes/2,MM.VRes*.7, " key out "+Str$(dev.out)+" "+Str$(K(new.key))+" ","CM",,2 Print "in"; new.dev; new.key, "out"; dev.out; K(new.key) EndIf Else log.codes 'if recorded codes don't exist, use Sub log.codes to record the key EndIf EndIf ready = 1 End Sub Do : Pause 10 : Loop ' spin the wheels between key presses Sub log.codes If (x = 0)And(R.new = 0) Then 'the first key press sets the new remote control R.new = new.dev 'record device code of new remote Print #3, : Print #3, "Sub K.data" Print "now press coresponding old remote key " Print #3, " 'Recorded "+DateTime$(NOW); EndIf If (x = 1)And(R.old = 0) Then 'the second key press sets the old remote control R.old = new.dev 'record device code of old remote Set.def.key = new.key 'set the default output key for any undefined input keys EndIf If (x Mod 2 = 0)And(new.dev = R.new) Then first.key=new.key :first.dev=new.dev 'record the keys of the new remote control Print "first dev-key = "; new.dev; new.key," Keys accepted so far = x "; x EndIf If (x Mod 2 = 0)And(new.dev = R.old)And(x > 1) Then Print "Wrong Remote - use the New remote"; new.dev; new.key,," x = "; x Exit Sub EndIf If x Mod 2 = 1 Then Print "second dev-key = "; new.dev; new.key,," x = "; x If (x Mod 2 = 1)And(new.dev = R.new)And(x > 2) Then Print "Wrong Remote - use the Old remote"; new.dev; new.key,," x = "; x Exit Sub EndIf If x Mod 16 = 0 Then : Print #3, : Print #3," "; : EndIf 'limit line length to 8 pairs If (x Mod 2 = 1)And(new.dev=R.old)And(first.dev=R.new) Then Print #3, "K("+Str$(first.key)+")="+Str$(new.key); 'add the keys of the old remote control & save If x Mod 16 <> 15 Then Print #3," : "; 'insert colon between records Print " Key pair recorded - K("+Str$(first.key)+") = "+Str$(new.key) EndIf Inc x Pause 333 'wait for any multiple key interups to pass End Sub Sub Finished 'add settings sub and restart program from saved file On KEY 0 Print #3, Print #3, "End Sub" Print #3, Print #3, "Sub settings" Print #3, " Key.data=1 : R.new=" R.new" : R.old=" R.old" : Set.def.key=" Set.def.key Print #3, "End Sub" Pause 99 Close #3 Key.data=1 Print "Finished and data saved - ressarting program from file" Pause 500 Run Fname$ End Sub Sub NECsend IRout As integer, dev As integer, key As integer Local integer word, d(2060), m, n = 1 word = (dev<<16) + (key<<8) + 255-key '32bit word = Device 16b + Key 8b + inverted Key 8b Math set 13, d() 'fill array with half-cycles, 13uS = duration of a half cycle @ 38kHz d(692) = 4500 'uS pause after 9mS of 38kHz to start For m = 734 To 2058 Step 42 'load data after start sequence d(m) = (((word>>(32-n)) And 1)*2 + 1) * 562.5'convert bits to pauses (0=562uS, 1=1687uS) Inc n 'step to next data bit Next Device bitstream IRout, 2058, d() 'send the data Pin(IRout) = 0 End Sub Sub K.data 'Recorded 05-03-2024 18:13:10 K(146)=26 : K(0)=56 : K(8)=18 : K(10)=8 : K(16)=226 : K(18)=152 : K(32)=224 : K(34)=122 K(40)=16 : K(42)=138 : K(48)=88 : K(50)=234 : K(66)=170 : K(72)=48 : K(80)=72 : K(82)=250 K(90)=242 : K(96)=104 : K(98)=186 : K(106)=232 : K(112)=112 : K(114)=218 : K(122)=210 K(136) =80 : K(138) =24 : K(144) =10 : K(160)= 42 : K(162)=74 : K(170)=154 : K(176)=50 K(178)=248 : K(194)=90 : K(200)=96 : K(202)=146 : K(208)=136 : K(210)=106 : K(216)=130 K(218)=144 : K(224)=168 : K(226)=66 : K(240)=176 : K(242)=58 : K(248)=128 : K(250)=160 End Sub Sub settings Key.data=1 : R.new= 192 : R.old= 251 : Set.def.key= 26 End Sub |
||||
morgs67 Regular Member Joined: 10/07/2019 Location: AustraliaPosts: 75 |
Thanks phil, will give it a go tomorrow. |
||||
phil99 Guru Joined: 11/02/2018 Location: AustraliaPosts: 2135 |
Updated PicoMite version of NECsend, just a few minor tweaks. Sub NECsend IRout As integer, dev As integer, key As integer 'Picomite V5.08.00 version Local integer word, d(2066), m, n = 1 word = (dev<<16) + (key<<8) + 255-key '32bit word = Device 16b + Key 8b + inverted Key 8b Math set 13, d() 'fill array with half-cycles, 13uS = duration of a half cycle @ 38kHz d(691) = 4500 'uS pause after 9mS of 38kHz to start For m = 733 To 2065 Step 42 'load data after start sequence d(m) = (((word>>(32-n)) And 1)*2 + 1) * 562.5'convert bits to pauses (0=562uS, 1=1687uS) Inc n 'step to next data bit Next Device bitstream IRout, 2066, d() 'send the data Pin(IRout) = 0 End Sub |
||||
Volhout Guru Joined: 05/03/2018 Location: NetherlandsPosts: 4228 |
Hi Phil, I checked the timing of NECsend on a pico, and even at 133 MHz CPUSPEED it was correct. I have no NEC IR remote, so cannot check the IRinput processing. I must have an F4 somwhere (playing tetris), when I can find it I will double check on the F4 if desired. Regards, Volhout P.S. what is the application of this program ? You have a new remote, and a (still working) old remote ? Both are NEC protocol. And this program translates the new remote buttons to old remote buttons because the device it controls does not understand the new codes ? I also have a "replacement" remote, but that remote was a "learning" remote, so it could record the old remote's codes (any, Sony, Philips, NEC, etc..) Edited 2024-03-22 20:01 by Volhout PicomiteVGA PETSCII ROBOTS |
||||
phil99 Guru Joined: 11/02/2018 Location: AustraliaPosts: 2135 |
I should have provided all the info. with the program but didn't think anyone would be interested. The TV is old and was manufactured for a now defunct local electronics store group - Dick Smith Electronics. The remote is quite flimsy and broke when I dropped it. Glued it together but now the buttons have worn away the graphite ink. I have temporarily solved that by putting a dot of glue on them and filing a 2H pencil tip over the glue. I have a couple of universal remotes but neither can produce the right codes. Because it is a "house" brand I doubt any can, except a learning one. This is sort of that, it can also learn Sony codes as the Pico IR function can read both. Found an old remote in the junk box so thought I would make a translator for it, just an excuse to use the Sub really. I found Select Case produced a noticeable lag with 45 buttons to sort through hence using array indices for the input codes and the array contents for the output codes. Almost instant response. Some wasted memory as only 45 out of 256 possibilities are used for this remote. The program copies itself to A:, appends the In and Out codes to the end of the copy, then copies that back to program memory and runs. Detecting the appended codes it switches to Translate mode. Not very sensible but interesting to write. Edited 2024-03-22 22:16 by phil99 |
||||
Print this page |