Re: IR Transmitter ?
Posted: 08 Mar 2017, 00:17
Hi.
I finish the RAW Code implementation.
The URL to invoke this method is:
http://192.168.1.101/control?cmd=IRSEND ... 38,512,256
IRSEND: Command Control
Type of IR: RAW
RAW Code as base2hex: 3U0GGL8AGGK588A22K58ALALALAGL1A22LAK45ALALALALALALALALAL1AK5
kHz: 38
Pulse Length: 512
Space Length: 256
Here is the modified _P035_IRTX.ino:
I've tested it with 2 buttons on different remotes.
1)
The red on/off button on "Top House" control:
Here is the Hex Bin file generated by IR Toy:
http://filebin.ca/3En22WfhfTDj/onoff_tophouse.bin
2)
The blue on/off button on Delonghi Air Conditioner:
Here is the Hex Bin file generated by IR Toy:
http://filebin.ca/3En2d3V91y99/onoff_delonghi.bin
In this case, the control sends a different code to turn on and to turn off. The file corresponds to "turn on".
The bin files format are described here: http://dangerousprototypes.com/docs/USB ... pling_mode
I save those files as .bin using GTKTerm on Linux.
To convert the .bin file into a base32hex string, I run (previously the variables pulse_len ad blank_len must be seted):
The things about base 64 where just for testing purpouses.
The resulting output is like:
For now, I think it's a start.
Things to improve:
Gustavo.
I finish the RAW Code implementation.
The URL to invoke this method is:
http://192.168.1.101/control?cmd=IRSEND ... 38,512,256
IRSEND: Command Control
Type of IR: RAW
RAW Code as base2hex: 3U0GGL8AGGK588A22K58ALALALAGL1A22LAK45ALALALALALALALALAL1AK5
kHz: 38
Pulse Length: 512
Space Length: 256
Here is the modified _P035_IRTX.ino:
Code: Select all
//#######################################################################################################
//#################################### Plugin 035: Output IR ############################################
//#######################################################################################################
#include <IRremoteESP8266.h>
IRsend *Plugin_035_irSender;
#define PLUGIN_035
#define PLUGIN_ID_035 35
#define PLUGIN_NAME_035 "Infrared Transmit"
boolean Plugin_035(byte function, struct EventStruct *event, String& string)
{
boolean success = false;
switch (function)
{
case PLUGIN_DEVICE_ADD:
{
Device[++deviceCount].Number = PLUGIN_ID_035;
Device[deviceCount].Type = DEVICE_TYPE_SINGLE;
Device[deviceCount].SendDataOption = false;
break;
}
case PLUGIN_GET_DEVICENAME:
{
string = F(PLUGIN_NAME_035);
break;
}
case PLUGIN_GET_DEVICEVALUENAMES:
{
break;
}
case PLUGIN_INIT:
{
int irPin = Settings.TaskDevicePin1[event->TaskIndex];
if (Plugin_035_irSender == 0 && irPin != -1)
{
addLog(LOG_LEVEL_INFO, "INIT: IR TX");
Plugin_035_irSender = new IRsend(irPin);
Plugin_035_irSender->begin(); // Start the sender
}
if (Plugin_035_irSender != 0 && irPin == -1)
{
addLog(LOG_LEVEL_INFO, "INIT: IR TX Removed");
delete Plugin_035_irSender;
Plugin_035_irSender = 0;
}
success = true;
break;
}
case PLUGIN_WRITE:
{
String IrType;
unsigned long IrCode;
unsigned int IrBits;
char log[120];
char command[120];
command[0] = 0;
char TmpStr1[100];
TmpStr1[0] = 0;
string.toCharArray(command, 120);
String cmdCode = string;
int argIndex = cmdCode.indexOf(',');
if (argIndex) cmdCode = cmdCode.substring(0, argIndex);
if (cmdCode.equalsIgnoreCase("IRSEND") && Plugin_035_irSender != 0)
{
success = true;
if (irReceiver != 0) irReceiver->disableIRIn(); // Stop the receiver
if (GetArgv(command, TmpStr1, 2)) IrType = TmpStr1;
if (IrType.equalsIgnoreCase("RAW")) {
String IrRaw;
unsigned int IrHz;
unsigned int IrPLen;
unsigned int IrBLen;
if (GetArgv(command, TmpStr1, 3)) IrRaw = TmpStr1;
if (GetArgv(command, TmpStr1, 4)) IrHz = str2int(TmpStr1);
if (GetArgv(command, TmpStr1, 5)) IrPLen = str2int(TmpStr1);
if (GetArgv(command, TmpStr1, 6)) IrBLen = str2int(TmpStr1);
printWebString += F("<a href='https://en.wikipedia.org/wiki/Base32#base32hex'>Base32Hex</a> RAW Code: ");
printWebString += IrRaw;
printWebString += F("<BR>");
printWebString += F("kHz: ");
printWebString += IrHz;
printWebString += F("<BR>");
printWebString += F("Pulse Len: ");
printWebString += IrPLen;
printWebString += F("<BR>");
printWebString += F("Blank Len: ");
printWebString += IrBLen;
printWebString += F("<BR>");
unsigned int buf[200];
unsigned int idx = 0;
unsigned int c0 = 0;
unsigned int c1 = 0;
printWebString += F("Interpreted RAW Code: ");
for(int i = 0; i < IrRaw.length(); i++)
{
char c = ((IrRaw[i] | ('A' ^ 'a')) - '0') % 39;
for (unsigned int shft = 1; shft < 6; shft++)
{
if ((c & 16) != 0) {
c1++;
if (c0 > 0) {
buf[idx++] = c0 * IrBLen;
for (uint t = 0; t < c0; t++)
printWebString += F("0");
}
c0 = 0;
} else {
if (c0+c1 != 0) {
c0++;
if (c1 > 0) {
buf[idx++] = c1 * IrPLen;
for (uint t = 0; t < c1; t++)
printWebString += F("1");
}
c1 = 0;
}
}
c <<= 1;
}
}
if (c0 > 0) {
buf[idx] = c0 * IrBLen;
for (uint t = 0; t < c0; t++)
printWebString += F("0");
}
if (c1 > 0) {
buf[idx] = c1 * IrPLen;
for (uint t = 0; t < c1; t++)
printWebString += F("1");
}
printWebString += F("<BR>");
Plugin_035_irSender->sendRaw(buf, idx+1, IrHz);
//sprintf_P(log, PSTR("IR Params1: Hz:%u - PLen: %u - BLen: %u"), IrHz, IrPLen, IrBLen);
//addLog(LOG_LEVEL_INFO, log);
//sprintf_P(log, PSTR("IR Params2: RAW Code:%s"), IrRaw.c_str());
//addLog(LOG_LEVEL_INFO, log);
} else {
if (GetArgv(command, TmpStr1, 2)) IrType = TmpStr1;
if (GetArgv(command, TmpStr1, 3)) IrCode = strtoul(TmpStr1, NULL, 16); //(long) TmpStr1
if (GetArgv(command, TmpStr1, 4)) IrBits = str2int(TmpStr1);
if (IrType.equalsIgnoreCase("NEC")) Plugin_035_irSender->sendNEC(IrCode, IrBits);
if (IrType.equalsIgnoreCase("JVC")) Plugin_035_irSender->sendJVC(IrCode, IrBits, 2);
if (IrType.equalsIgnoreCase("RC5")) Plugin_035_irSender->sendRC5(IrCode, IrBits);
if (IrType.equalsIgnoreCase("RC6")) Plugin_035_irSender->sendRC6(IrCode, IrBits);
if (IrType.equalsIgnoreCase("SAMSUNG")) Plugin_035_irSender->sendSAMSUNG(IrCode, IrBits);
if (IrType.equalsIgnoreCase("SONY")) Plugin_035_irSender->sendSony(IrCode, IrBits);
if (IrType.equalsIgnoreCase("PANASONIC")) Plugin_035_irSender->sendPanasonic(IrBits, IrCode);
}
addLog(LOG_LEVEL_INFO, "IR Code Sent");
if (printToWeb)
{
printWebString += F("IR Code Sent ");
printWebString += IrType;
printWebString += F("<BR>");
}
if (irReceiver != 0) irReceiver->enableIRIn(); // Start the receiver
}
break;
}
}
return success;
}
1)
The red on/off button on "Top House" control:
Here is the Hex Bin file generated by IR Toy:
http://filebin.ca/3En22WfhfTDj/onoff_tophouse.bin
2)
The blue on/off button on Delonghi Air Conditioner:
Here is the Hex Bin file generated by IR Toy:
http://filebin.ca/3En2d3V91y99/onoff_delonghi.bin
In this case, the control sends a different code to turn on and to turn off. The file corresponds to "turn on".
The bin files format are described here: http://dangerousprototypes.com/docs/USB ... pling_mode
I save those files as .bin using GTKTerm on Linux.
To convert the .bin file into a base32hex string, I run (previously the variables pulse_len ad blank_len must be seted):
Code: Select all
#!/usr/bin/python
b32 = "0123456789ABCDEFGHIJKLMNOPQRSTUV"
b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
def bits32(bits):
rdo = ""
while len(bits) > 0:
subBits = bits[-5:]
bits = bits[:-5]
rdo = b32[int(subBits,2)] + rdo
return rdo
def bits64(bits):
rdo = ""
while len(bits) > 0:
subBits = bits[-6:]
bits = bits[:-6]
rdo = b64[int(subBits,2)] + rdo
return rdo
bits = ""
#pulse_len = 550
#blank_len = 550
pulse_len = 533
blank_len = 277
idx = 0
with open("onoff_delonghi.bin", "rb") as f:
byte = f.read(1)
while byte != "":
idx += 1
if idx % 4 == 1 or idx % 4 == 3:
byte_h = ord(byte)
if idx % 4 == 2 or idx % 4 == 0:
measure = ord(byte) + (byte_h << 8)
if measure != 0xFFFF:
ms = measure * 21.3333
mtype = "Blank"
bv = "0"
ds = blank_len
if idx % 4 == 2:
mtype = "Pulse"
bv = "1"
ds = pulse_len
cbits = round(ms / ds,0)
print "%s: %s - %u ms - cbits: %.3g" % \
(mtype, format(measure, '04x'), ms, cbits)
for i in range (0, int(cbits)):
bits += bv
# Do stuff with byte.
byte = f.read(1)
print "Rdo: %s\nHex: %s\nB32: %s\nB64: %s" % (bits,hex(int(bits,2)),bits32(bits), bits64(bits))
The resulting output is like:
The base32hex string that should be used is "B32".Pulse: 0018 - 511 ms - cbits: 1
Blank: 000e - 298 ms - cbits: 1
Pulse: 0018 - 511 ms - cbits: 1
Blank: 0030 - 1023 ms - cbits: 4
Pulse: 0018 - 511 ms - cbits: 1
Blank: 000e - 298 ms - cbits: 1
Pulse: 0018 - 511 ms - cbits: 1
Rdo: 111111000000100001000010101010000101010000100001010000101010000100001010000100001010100001010100001010101010101010101010101010101010100001010100001010100001000010101010101010100001000010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010100001010101010000101
Hex: 0x1f8108550a8428542142150a85555555550a85421555421555555555555555555555550aa85L
B32: 3U0GGL8AGGK588A22K58ALALALAGL1A22LAK45ALALALALALALALALAL1AK5
B64: H4EIVQqEKFQhQhUKhVVVVVUKhUIVVUIVVVVVVVVVVVVVVVUKqF
For now, I think it's a start.
Things to improve:
- Improve Python script to accept params instead of setting it in the code.
- Improve Python script to read "space / pulse" text files
- Improve Python script to automatically determine pulse and blank length
- Improve _P016_IR.ino to inform a base32hex in case an Unkown Type is received.
- Suggest the _P035_IRTX.ino diffs to be accepted on master branch. (I've to read about how to do it)
Gustavo.