Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 01:15 26 Nov 2024 Privacy Policy
Jump to

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: Australia
Posts: 75
Posted: 04:33am 22 Jan 2024
Copy link to clipboard 
Print this post

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: Australia
Posts: 6098
Posted: 05:07am 22 Jan 2024
Copy link to clipboard 
Print this post

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: Australia
Posts: 2135
Posted: 05:15am 22 Jan 2024
Copy link to clipboard 
Print this post

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: Australia
Posts: 75
Posted: 05:41am 22 Jan 2024
Copy link to clipboard 
Print this post

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: Australia
Posts: 2135
Posted: 06:07am 10 Feb 2024
Copy link to clipboard 
Print this post

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

 Print
 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: Australia
Posts: 2135
Posted: 05:21am 12 Feb 2024
Copy link to clipboard 
Print this post

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

 Print
 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: Australia
Posts: 75
Posted: 07:11am 21 Feb 2024
Copy link to clipboard 
Print this post

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: Australia
Posts: 2135
Posted: 12:11pm 21 Feb 2024
Copy link to clipboard 
Print this post

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: Australia
Posts: 75
Posted: 08:39am 04 Mar 2024
Copy link to clipboard 
Print this post

  phil99 said  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


 Print
 c(66)=1    'end pulse time units

End Sub


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: Australia
Posts: 2135
Posted: 11:52am 04 Mar 2024
Copy link to clipboard 
Print this post

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
Sub 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
Print "settings - Key data recorded"; Key.data,"new device"; R.new,"old device"; R.old,"default key"; Set.def.key
Print
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
And this the sort of data it appends to the program
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: Australia
Posts: 75
Posted: 12:23pm 04 Mar 2024
Copy link to clipboard 
Print this post

Thanks phil, will give it a go tomorrow.
 
phil99

Guru

Joined: 11/02/2018
Location: Australia
Posts: 2135
Posted: 07:44am 22 Mar 2024
Copy link to clipboard 
Print this post

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: Netherlands
Posts: 4228
Posted: 09:42am 22 Mar 2024
Copy link to clipboard 
Print this post

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: Australia
Posts: 2135
Posted: 12:14pm 22 Mar 2024
Copy link to clipboard 
Print this post

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


To reply to this topic, you need to log in.

© JAQ Software 2024