Utility:Convert X10 to Insteon Program with a PLC

September 5, 2009 at 1:44 pm | In General, Software Setup | Leave a Comment
Tags: , , , , ,

Hi, so I know ive been disconnected for a while.  But always trying to provide some goodies.

One of the cool things of the PLC is that if you know serial commands you can actually talk to it bypassing the SDM software.  My reason being that X10 motion sensors are cheeper than the Insteon and smaller which I can hide in different places but I would run in to the problem of the x10 signals not making it back to my main computer.  So what If you can have something on another computer which can transalate it to Insteon ?:)

So what I was right on the back of the PLC I have a transceiver and use the PLC with this small code to convert it to Insteon.  This way I basically have a x10 receiver on the other leg of my home.

So below is a small little program I use to  ‘convert’ X10 signals to a Insteon signal.  In my case the PLC will sending a ON  or OFF command to the PLM and depending the rate is the house code for example (B5,B6).   For the example im using VB 2005.  2008 and 2010 will work fine as well.  Note that i am bypassing entirely the SDM software.  if you don’t call it in your code it wont load, but you do have the port locked and isn’t sharable  :)

A very good starting point is this site and I basically started from here http://www.madreporite.com/insteon/insteon.html which will show you how read bytes, which is how the plc will respond as well.

Basically the PLC talks at 4800,8,N,1.  The program consist of a simple form with  just one button to exit.


Option Strict Off
Option Explicit On
Imports VB = Microsoft.VisualBasic
Imports System.IO
Imports System.IO.Ports
Imports System.Net

Public Class Form1
 Public WithEvents PLC As New IO.Ports.SerialPort
 Public X10_House_Code As String
 Public X10_House_VALUE As Integer
 Public X10_Command As String
 Public PLC_Queue As String
 Public handler As New mySerialDelegate(AddressOf Process_Queue)  ' Once we read the data process it in a separate thread.

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
 '------ OPEN PLC SERIAL CONNECTION SETUP PLC AND LEAVE READY - 
 PLC.PortName = "COM1"
 PLC.BaudRate = 4800
 PLC.DataBits = 8
 PLC.Parity = Parity.None
 PLC.StopBits = StopBits.One
 If PLC.IsOpen = False Then PLC.Open()

End Sub

 '---- THIS IS THE EVENT THAT WILL FIRE EACH TIME DATA IS RECEIVED BASICALLY WE CAPTURE ALL THE DATA AND
 '---- CALL THE OTHER THEAD TO CONVERT IT.
 Private Sub PLC_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles PLC.DataReceived
 Dim A, Bytes_to_read As Integer
 Dim rcvBuf(4096) As Byte
 Bytes_to_read = PLC.BytesToRead
 Do While PLC.BytesToRead > 0
 PLC.Read(rcvBuf, 0, rcvBuf.Length)
 For A = 0 To Bytes_to_read - 1
 PLC_Queue = PLC_Queue + Hex(rcvBuf(A)).PadLeft(2, "0") + " "
 Next
 Bytes_to_read = PLC.BytesToRead

 Loop

 Me.BeginInvoke(handler)
 End Sub

 Public Delegate Sub mySerialDelegate()
 Public Sub Process_Queue()

 'CONVERT STEAM TO X10 HOUSE CODES and the VALUE THAT WILL BE PASS TO THE OTHER DEVICE
 ' SO WHEN IT SEEN B2 IT WILL SEND TO THE OTHER SIDE A VALUE OF 18 ON THE RATE OR 'ON' VALUE
 ' Im only converting the B Code nothing else. 

 If PLC_Queue.Contains("02 4A 00 EE ") Then X10_House_Code = "B2" : X10_House_VALUE = 18
 If PLC_Queue.Contains("02 4A 00 E2 ") Then X10_House_Code = "B3" : X10_House_VALUE = 19
 If PLC_Queue.Contains("02 4A 00 EA ") Then X10_House_Code = "B4" : X10_House_VALUE = 20
 If PLC_Queue.Contains("02 4A 00 E1 ") Then X10_House_Code = "B5" : X10_House_VALUE = 21
 If PLC_Queue.Contains("02 4A 00 E9 ") Then X10_House_Code = "B6" : X10_House_VALUE = 22
 If PLC_Queue.Contains("02 4A 00 E5 ") Then X10_House_Code = "B7" : X10_House_VALUE = 23
 If PLC_Queue.Contains("02 4A 00 E4 ") Then X10_House_Code = "B8" : X10_House_VALUE = 24
 If PLC_Queue.Contains("02 4A 00 E7 ") Then X10_House_Code = "B9" : X10_House_VALUE = 25
 If PLC_Queue.Contains("02 4A 00 EF ") Then X10_House_Code = "B10" : X10_House_VALUE = 26
 If PLC_Queue.Contains("02 4A 00 E3 ") Then X10_House_Code = "B11" : X10_House_VALUE = 27
 If PLC_Queue.Contains("02 4A 00 EB ") Then X10_House_Code = "B12" : X10_House_VALUE = 28
 If PLC_Queue.Contains("02 4A 00 E0 ") Then X10_House_Code = "B13" : X10_House_VALUE = 30
 If PLC_Queue.Contains("02 4A 00 E8 ") Then X10_House_Code = "B14" : X10_House_VALUE = 31
 If PLC_Queue.Contains("02 4A 00 E4 ") Then X10_House_Code = "B15" : X10_House_VALUE = 32
 If PLC_Queue.Contains("02 4A 00 EC ") Then X10_House_Code = "B16" : X10_House_VALUE = 32

 '- ON OR OFF
 If PLC_Queue.Contains("02 4A 01 E2 ") Then X10_Command = "ON" : Send_Bytes(X10_House_VALUE, True) : Debug.Print(X10_House_Code) : X10_House_Code = "" : X10_Command = ""
 If PLC_Queue.Contains("02 4A 01 E3 ") Then X10_Command = "OFF" : Send_Bytes(X10_House_VALUE, False) : Debug.Print(X10_House_Code) : X10_House_Code = "" : X10_Command = ""

 Debug.Print(PLC_Queue)

 ' Clear and start again
 PLC_Queue = ""
 End Sub

Public Function Send_Bytes(ByVal value As Integer, ByVal State As Boolean) As Boolean
 Dim RECEIVER() As String = Split("0D.FE.9E", ".")  '-- THIS CONTAINS WHO WE ARE SENDING THE MESSAGE TO CHANGE AS NECESSARY
 '-- MAGIC CODE TO SEND TO PLC (I'LL EXPLAIN THEM LATER)
 Dim xmtbuf() As Byte = {&H2, &H40, &H1, &HA1, &H0, &H9, &HFD, &HE4, &H0, &H0, &H0, &HD, &HB, &H44, &H5, &H11, &H1}

 '-- HERE WE WILL REPLACE THE BYTES ABOVE IN BOLD TO WANT TO SEND TO,
 xmtbuf(11) = System.Convert.ToInt32(RECEIVER(0), 16)
 xmtbuf(12) = System.Convert.ToInt32(RECEIVER(1), 16)
 xmtbuf(13) = System.Convert.ToInt32(RECEIVER(2), 16)

 '- DEPENDING ON THE DEVICE BEING ON OR OFF WE SWAP ONE OF THE BYTES
 If State = True Then xmtbuf(15) = 17 Else xmtbuf(15) = 19 ' If on then push 17 if off push 19

 '--- HERE WE INSERT THE VALUE / X10 HOUSE CODE WE HAVE PREDIFINED 
 xmtbuf(16) = value

 '--- CALL OUR LITTLE FUNCTION TO WRITE THE BYTES TO THE SERIAL PORT
 PLC_Write(xmtbuf)

 '--- SETUP SOME MORE BYTES (THIS DOENST CHANGE) AND WRITE THEM, THIS TELLS THE PLC TO PROCESS THE BYTES WE SENT
 '--- BEFORE
 Dim xmtBuf2() As Byte = {&H2, &H46, &H1, &H42, &H10, &H9F}
 PLC_Write(xmtBuf2)
 End Function

 '--- THIS FUNCTION BASICALY WRITES ALL BYTES TO THE SERIAL PORT WE HAVE PREVIOUSLY DEFINED
 Public Function PLC_Write(ByVal XmtBuf As Object) As Boolean
 Try
 PLC.Write(XmtBuf, 0, XmtBuf.Length)
 Catch
 Debug.Print("COULDNT SEND DATA CHECK PORT")
 End Try

 End Function

 '--- SIMPLE BUTTON ON OUR FORM TO EXIT THE PROGRAM
 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
 End
 End Sub
End Class

Getting / Setting Insteon information from the Venstar T1700 thermostat

March 1, 2009 at 3:29 pm | In General, Hardware setup, Software Setup | 4 Comments
Tags: , , , , , , , , , , , , ,

We’ll after receiving back some of my hard earned money thru 2008. I shelved out the $159 for the Insteon T1700 thermostat.
It can be found here.

The device is quite small, which is fine and thinner that my orginary Honeywell one which was a real plus.  To install was also very simple.
And technical support was awesome!!!  Who expects to call a company and receive a live person and be able to troubleshoot on the phone in less that 3 min.  And to top it off the rep even called me back since he had to leave. At the end it was a simple dip switch due to my model.  So if after you install it and when you turn on cool and heat comes out and vice-versa, just turn on dip switch two and your set!  Thats Again Mike from Venstar!!!!


The only thing would be the ‘light’ on the side of the Insteon module.  so in dark areas it does stand out.
Like mentioned above the device is very small and the insteon module even smaller.
For example check out the image in comparison to my hand

Setting Mode, Getting Temperature of Thermostat

Ok, enough Pictures and talk, lets see how to control this device.

First forget about sending ON/OFF commands, for me they didnt work, nor did they do anything.  What we will be using is the 0×02 command instead of 0×11 for on or 0×13 for OFF.  What I has able to find was the higher numbers after that worked. I’ll show you what

Ive got and show examples after.  In my case I couldnt send request using the regular PLC commands so I ended using the low level calls using the sendhex function, that article can be found here

More ways to speak to your Insteon Devices

For the examples my PLC is # “0D 51 32” and my Thermostat is “01 02 03“.

0×6b – Bit 2 – Get Thermostat Mode (Returned is 00=off,01=Heat,02=Cool,03=Auto,04=Fan)

 
	'Send

	Sm.SendPLCHex("02 40 01 A1 00 09 FD 9B 0D 51 32 01 02 03 05 6B 02"	Sm.SendPLCHex("02 46 01 42 10 9F") ' Execute my command

	'You should get the reponse on the Last Bit of your reponse.  For example
	04 01 02 03 0D 51 32 26 6B 02

	So in this case 0x02 Means the device is on COOL.

0×6b – Bit 3 - Get Temperature (Returned is the temperature, you convert to decimal and divide by two)

	'Send
	Sm.SendPLCHex("02 40 01 A1 00 09 FD 9B 0D 51 32 01 02 03 05 6B 03")
	Sm.SendPLCHex("02 46 01 42 10 9F") ' Execute my command
	'You should get the reponse on the Last Bit of your reponse.  For example
	04 01 02 03 0D 51 32 26 6B 9A 
	So in this case 0x9A Converted to decimal is 154 divide
        that by two and you get 77 degrees!!

0x6b - Bit 4 - Set to Heat
'Send

Sm.SendPLCHex("02 40 01 A1 00 09 FD 9B 0D 51 32 01 02 03 05 6B 04")

Sm.SendPLCHex("02 46 01 42 10 9F") ' Execute my command

0x6b - Bit 5 - Set to Cool
'Send

Sm.SendPLCHex("02 40 01 A1 00 09 FD 9B 0D 51 32 01 02 03 05 6B 05")

Sm.SendPLCHex("02 46 01 42 10 9F") ' Execute my command

0×6b – Bit 6 – Set to Auto (To switch automatically from Cool to Heat depending on your settings)

	'Send
	Sm.SendPLCHex("02 40 01 A1 00 09 FD 9B 0D 51 32 01 02 03 05 6B 06")
	Sm.SendPLCHex("02 46 01 42 10 9F") ' Execute my command

0×6b – Bit 7 - Fan on

	'Send
	Sm.SendPLCHex("02 40 01 A1 00 09 FD 9B 0D 51 32 01 02 03 05 6B 07")
	Sm.SendPLCHex("02 46 01 42 10 9F") ' Execute my command

0×6b – Bit 8 – Fan off

	'Send
	Sm.SendPLCHex("02 40 01 A1 00 09 FD 9B 0D 51 32 01 02 03 05 6B 08")
	Sm.SendPLCHex("02 46 01 42 10 9F") ' Execute my command

0×6b – Bit 9 – All Off

	'Send
	Sm.SendPLCHex("02 40 01 A1 00 09 FD 9B 0D 51 32 01 02 03 05 6B 09")
	Sm.SendPLCHex("02 46 01 42 10 9F") ' Execute my command

Setting the Cool / Heat Thermostat Temperature

Here insteon of 0×6B we will be using the 0×6C for Cool and 0×6D for HEAT.  So lets say you’ve set your device to Cool and want to lower it to 75 Degrees.  Just like when we read the temperature, when we set it we need to multiply the requested value * 2 and convert it to HEX.  In the sample below the variable Set_Temp holds what we want it to.  The next statement converts it to HEX and *2 and presto!

'This is the temperature we want to set Cool to!
Set_Temp="75"
Dim Temp As String = Hex(Set_Temp * 2)
Sm.SendPLCHex("02 40 01 A1 00 09 FD 9B 0D 51 32 01 02 03 05 6C " + Temp)
Sm.SendPLCHex("02 46 01 42 10 9F")

'This is the temperature we want to set heat to!
Set_Temp="70"
Dim Temp As String = Hex(Set_Temp * 2)
Sm.SendPLCHex("02 40 01 A1 00 09 FD 9B 0D 51 32 01 02 03 05 6D " + Temp)
Sm.SendPLCHex("02 46 01 42 10 9F")

Hope this works for you and its working great for me.  Each hour I poll the temperature and as part of that routine I poll my thermostat to keey the information up to date. I’ll post more as I find out!

Software: Get Insteon / Talking to your PC – Part 2

June 20, 2008 at 12:51 pm | In Software Setup | 6 Comments
Tags: , , , , ,

Part 2.

As requested, here are some live examples,  this is of course using the SDM library in VB 2005, the same works for VB6.
Since my blog is really about my home project, a VERY GOOD site,  which is the one I used to start which has lots of specs and examples in VB6 about these commands. Its called Efundies.com, I wouldn’t like to re-invent the wheel.

My examples are using the SDM.SendinsteonRaw command, I find them faster since you don’t wait for a return.  For our examples we can use the source as “00 00 00″ or the actually # on the PLC and the
rate is the actual intensity of the command. you can also use the sm.SendINSTEON(Device ID,command 1, command 2,hops) but it will wait for a reply.  I like to catch the response on the way back. And example using that command would be
sm.SetOnLevelText(“07.B1.12″, “100%”) – And here you DO have to use the dots. :)   A list of most of the commands that can be used when the SDM is properly load are here

We’ll use as examples for our program that the device we want to control is

In our program previously defined,
You can download the SDM device manager here.  Also some information regarding the PLC can be found here (This is the one I have) – worth every $

Option Explicit on
Friend WithEvents Sm As SDM3Server.SDM3

 Public Sub MainMenu_Load(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles MyBase.Load
 Sm = New SDM3Server.SDM3  - Create a instance of the SDM using (SM)

 Dim Mac as string = "11 22 BB"
 Dim Rate as integer = 255

Mac = “11 22 BB”
Rate = Intensity of the device (Since we are using raw commands this runs from 0,256 and needs to be converted to HEX”
The last #3, which is the Hops= I keep as 3 (Always works for me.)

Notes: All values are in HEX, also you need to put spaces in your device address, in my case I pull them off a SQL Database but they come in as “11 22 33″ if you put (.) dots or any other characters the command wont work.

Turn onSm.SendINSTEONRaw(“00 00 00 ” + Mac + ” 05 11 ” + Hex(Rate), 3) – Turn on device to the desired rate to 255 is the same as Sm.SendINSTEONRaw(“00 00 00 ” + Mac + ” 05 11 FF“), 3) – Turn on 100%
This will turn on the device at the predefined RAMP rate so if you have setup a slow ramp rate this is the one to use.  For example ICON Dimmers have no ramp rate (options) so this will turn on at .1 seconds

Turn on fast- Sm.SendINSTEONRaw(“00 00 00 ” + Mac + ” 05 12 ” + Hex(Rate), 3) – Turn on device to the desired rate to 255 is the same as Sm.SendINSTEONRaw(“00 00 00 ” + Mac + ” 05 11 FF“), 3) - Turn on 100%
This will turn on the device at fast redgardless of the  predefined RAMP rate.

Turn offSm.SendINSTEONRaw(“00 00 00 ” + Mac + ” 05 13 00″, 3)
This will turn off the device at the predefined RAMP rate so if you have setup a slow ramp rate this is the one to use.

Turn off fast- Sm.SendINSTEONRaw(“00 00 00 ” + Mac + ” 05 14 ” + Hex(Rate), 3) – Turn on device to the desired rate to 255 is the same as Sm.SendINSTEONRaw(“00 00 00 ” + Mac + ” 05 11 FF“), 3) – Turn on 100%
This will turn on the device at fast redgardless of the  predefined RAMP rate. For example ICON Dimmers have no ramp rate (options) so this will turn off at .1 seconds

Brighten up one step - sm.SendINSTEONRaw(“00 00 00 “+Mac+” 05 15 00″, 3)
Each device has 32 levels of so this will just bump down or up one.  Good for dimming without knowing the previous value.  You can dim to 0.

Dim down one step - sm.SendINSTEONRaw(“00 00 00 “+Mac+” 05 16 00″, 3)
Each device has 32 levels of so this will just bump down or up one.  Good for dimming without knowing the previous value.  You can dim to 0.

Get status of device – sm.SendINSTEONRaw(“00 00 00 11 22 BB 05 19 00″, 3)
Using Alternet command sm.GetOnLevelText “11.22.BB”

Sending a Inteson group message; Groups allow you to send messages to a set of devices (1,2,10,100,200 with one command) Only bad things is you dont get a reply from the devices
I have found I had to run this twice sometimes but (We’ll get to groups later) .

Turn off group #20 (Remember HEX!) – sm.SendINSTEONRaw(“00 00 00 00 00 20 CF 13 00″, 3) ‘ SEND broadcast group 20 OFF!

Turn on group #20 – sm.SendINSTEONRaw(“00 00 00 00 00 20 CF 11 FF”, 3) ‘ SEND broadcast group 20 ON

The PLC also send X10 commands, for this I use theSendX10 command, this command WILL pause and wait for a response. For example

Sm.SendX10(“D02,DON”) ‘ TURN ON Device D02
Sm.SendX10(“D02,DOFF”) ‘ TURN ON Device D02

Blog at WordPress.com. | Theme: Pool by Borja Fernandez.
Entries and comments feeds.